------- android培训、 java培训、期待与您交流! ----------

1. 字符编码和解码

在Java中,字符编码指的是:将字符串转换成字节数组,转换的方法是通过方法getByte()实现的,该方法可以指定编码表,也可以不指定,不指定编码表则使用默认的编码表。下面,我们将通过字符编码和解码,解决如何给字符编码以及解码。

1.1 字符编码

下面的例子,将中文字符进行编码,并指定编码表。控制台的输出结果为:

-60, -29, -70, -61,
-28, -67, -96, -27, -91, -67,
从输出结可以知道,GBK编码的中文字符,一个字符占两个字节。UTF-8编码的中文字符,一个字符占3个字节。

package com.itheima.entranceExam.blog;import java.io.IOException;public class encodeTest {public static void main(String[] args) throws IOException {String s = "你好";//编码:将字符串变成字节数组,指定编码表为GBKbyte[] b1 = s.getBytes("GBK");//编码:将字符串变成字节数组,指定编码表为UTF-8byte[] b2 = s.getBytes("UTF-8");//遍历字节数组中的元素for(byte b : b1) {System.out.print(b+", ");}System.out.println();//遍历字节数组中的元素for(byte b : b2) {System.out.print(b+", ");}}
}

1.2 解码

下面我们对1.1节中编码的中文字符进行解码,解码就是将字符转成的字节数组,从新转换成原来的字符。解码时可以指定编码表也可以不指定,不指定编码表则使用默认是编码表。

package com.itheima.entranceExam.blog;import java.io.IOException;public class encodeTest {public static void main(String[] args) throws IOException {String s1 = "你好";//编码,指定编码表为GBKbyte[] b1 = s1.getBytes("GBK");//解码,指定编码表为GBKString s2 = new String(b1, "GBK");System.out.println(s2);//输出"你好",没有乱码}
}

1.3 编码表不一致导致的问题

注意:当我们编码使用的编码表和解码使用的编码表不一致时,则会出现乱码。下面的例子编码时使用的编码表是UTF-8,而解码使用到编码表是GBK。将字符串"你好"使用UTF-8进行编码,解码时使用GBK,为什么输出结果是三个中文字符"浣犲ソ"?下面我们通过图片来分析:UTF-8编码中文字符串"你好",这两个中文字符串变成6个字节的字节数组。解码时使用GBK编码表,GBK编码表将字节数组中的,每两个联系的字节数组变成一个中文字符,长度为6的字节数组就变成3个中文字符,所以下面例子的2个中文字符解码后,会出现3个中文字符。

代码:

package com.itheima.entranceExam.blog;import java.io.IOException;public class encodeTest {public static void main(String[] args) throws IOException {String s1 = "你好";//编码,指定编码表为UTF-8byte[] b1 = s1.getBytes("UTF-8");//解码,指定编码表为GBKString s2 = new String(b1, "GBK");System.out.println(s2);//输出"浣犲ソ"}
}

1.4 解决乱码问题

当编码和解码使用的编码表不一致时,会出现乱码,出现乱码该如何解决呢?

下面的例子演示:编码时使用GBK编码表,解码时使用ISO8859-1编码表,致使出现乱码,如何解决乱码吗?

下面结合图片进行说明(代码也在下面):

出现乱码的应用是,GBK编码表中一个中文字符对应两个字节数组数据,ISO8859-1是拉丁码表和欧洲码表,ISO8859-1编码表一个二进制的字节数组数据对应一个字符。所以两个中文字符GBK编码后,再使用ISO8859-1解码时会出现4个字符的乱码。解决该乱码的步骤是:

1. 将ISO8859-1解码后返回的字符串进行ISO8859-1编码,编码后返回字节数组。

2. 将上面的字节数组进行GBK解码,就能获得原来的中文字符了。

注意:编码使用GBK,解码使用UTF-8。为了解决乱码,二次编码如果使用UTF-8,解码使用GBK时,会出现问题,所以上面的方案不是在任何编码中都可以使用的。

代码:

package com.itheima.entranceExam.blog;import java.io.IOException;public class encodeTest {public static void main(String[] args) throws IOException {String s = "你好";//编码,使用GBK编码表byte[] b1 = s.getBytes("GBK");//解码,使用ISO8859-1编码表String s1 = new String(b1,"ISO8859-1");//下面一行输出结果为:ÄãºÃ,出现乱码,因为编码和解码使用的编码表不同System.out.println(s1);//下面分析如何解决乱码问题//1. 将ISO8859-1解码获得的字符串s1,使用ISO8859-1编码表进行再编码,返回字节数组byte[] b2 = s1.getBytes("ISO8859-1");//2. 将字节数组使用GBK字符集进行解码String s2 = new String(b2, "GBK");//输出结果:你好,乱码问题解决了System.out.println(s2);}
}

2. 字符联通

2.1 字符联通问题

新建一个文本文件,在该文本文件中输入“联通”两个字符,保存并关闭文本文件。重新打开文本文件,发现文本文件中出现了乱码,如下图。

这是为什么呢?因为输入“联通”字符时,使用的是系统默认的中文编码表GBK,而文本文件是一个应用程序,它默认使用的是UTF-8编码,所以再次打开时会出现乱码。

所有当保存文本文件时,选择另存为UTF-8编码方式,就不会出现乱码了。

2.2 GBK和UTF-8编码识别原理

GBK编码的中文,2个字节代表一个中文。UTF-8编码的中文,3个字节代表一个中文。不论是GBK还是UTF-8,中文对应的编码都是负数,既然都是负数,那么怎么知道只读3个字节或者只读2个字节作文中文呢?

下面通过图片分析:

转换流读取方法是一次读取一个字节,两个字节变成一个中文字符。而FileReader的read方法是一次读取两个字节,返回一个中文。但是如果数据是UTF-8编码出来的数据,使用GBK解码时会出现乱码。而且在UTF-8编码表中,有可能2个字节代表一种字符,有可能3个字节代表一个中文。那如何知道读取两个字节还是3个字节呢?

其实UTF-8的编码表都添加一个标识头信息。根据该标识头信息,就知道一次读取1个字节,还是2个字节或者是3个字节。在IO包下的DataInputStream下有UTF-8标志头说明信息,下面一节讲解UTF-8的格式,来说明标志头信息的作用。

2.3 UTF-8编码格式

在IO包下找到DataInputStream,找到UTF-8修改版,就可以看到UTF-8的格式信息,如下。

一个字节代表一个字符:一个字节的8位数据中,头尾数据为0,表示该一个字节代表一个字符,如下图:

两个字节代表一个字符:第一个字节的前3位是110,第2个字节的前2位是10,说明两个字节代表一个字符,如下图:

三个字节代表一个字符:第1个字节的前4位是1110,第2个字节的前2位是10,第3个字节的前2位是10,说明三个字节代表一个字符。如下图:

2.4 分析UTF-8的编码格式以及“联通”问题产生的原因

下面我们通过代码例子,分析2.3节中的UTF-8的编码格式,并且分析2.1节中字符联通问题产生的原因。

package com.itheima.entranceExam.blog;import java.io.IOException;public class encodeTest {public static void main(String[] args) throws IOException {String s = "联通";//GBK编码byte[] buf = s.getBytes("GBK");//变量字节数组for(byte b : buf) {//&255 是为了去掉前面的数据,只保留后面8位二进制数据,因为一个字节占8为System.out.println(Integer.toBinaryString(b&255));}}
}

代码输出结果为:

11000001
10101010
11001101
10101000

下面通过图片分析该输出结果的中隐含的UTF-8编码格式,已经字符联通问题原因:

分析字符联通产生的原因:

上面代码中,中文字符使用GBK编码,但是编码后的的二进制数据正好和UTF-8格式吻合:第1个字节110开头,说明两个字节代表一个字符(110打头的代表第1个字节,10打头的代表第2个字节)。所以文本编辑器把这些字符("联通")去查UTF-8编码表,解码成了UTF-8对应的字符,所以显示的结果会出现问题。这就是2.1节问题产生的原因。

如果在文本文件中输入中文 " 你联通 " ,保存文本文件并关闭。再次打开后,就不会出现2.1那样的问题,因为中文 " 你 "在编码表中对应的二进制数据不符合UTF-8的格式,所以编辑器使用GBK解码,后面的 " 联通 "当然也使用GBK解码,所以不会出现2.1的问题:

黑马程序员——字符编码以及字符联通相关推荐

  1. 黑马程序员——总集篇

    -----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 本人编写技术博客的时候只是针对章节的一些比较重要的知识点来编写的: 个人感觉质量 ...

  2. 黑马程序员——Java字符流、字节流IO流

    黑马程序员--Java字符流.字节流Io流 ---------------------- <a href="http://www.itheima.com"target=&qu ...

  3. 【黑马程序员 C++教程从0到1入门编程】【笔记1】数据类型、运算符、程序流程结构、数组、函数、指针、结构体

    黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难 文章目录 1.C++初识 1.1 第一个c++程序 1.2 注释 1.3 变量 1.4 常量 1.5 关键字 1.6 标识符命名规则 2 ...

  4. 黑马程序员入学Java知识——精华总结

    黑马程序员入学Java知识--精华总结 J2SE部分,Java高新技术部分,7K面试题部分等黑马入学要求的知识点总结! 一.黑马程序员-java概述与基础知识 6 1.何为编程? 6 2.Java语言 ...

  5. JavaScript学习笔记--【黑马程序员】

    目录 一.编程语言 1.1 编程 1.2 计算机语言 1.3 编程语言 1.4 翻译器 1.5 编程语言和标记语言区别 总结 二.计算机基础 2.1 计算机组成 2.2.数据存储 2.3 数据存储单位 ...

  6. 黑马程序员:Java基础总结----Java语言编程规范

       黑马程序员:Java基础总结        Java语言编程规范:参考自SUN公司文档  ASP.Net+Android+IO开发..Net培训.期待与您交流!  I.   排版规范 A.  规 ...

  7. 黑马程序员C++笔记

    C++ 课程链接: 黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难_哔哩哔哩_bilibili 一.C++基础语法 1.变量和常量数据 1.1第一个C++程序 编写一个C++程序总共分 ...

  8. [学习笔记]黑马程序员-Hadoop入门视频教程

    文章目录 参考资料 第一章:大数据导论与Linux基础(p1-p17) 1.1 大数据导论 1.1.1 企业数据分析方向 1.1.2 数据分析基本流程步骤 明确分析的目的和思路 数据收集 数据处理 数 ...

  9. 黑马程序员_基础测试

    -------android培训.java培训.期待与您交流! ---------- 黑马程序员训练营基础测试题及个人代码(包含思路.步骤和基本注释) 1. 编写程序计算12+22+32+....+1 ...

  10. 黑马程序员 一、java 概述与基础知识

    获取更多资源关注Java帮帮IT资源分享网 一.黑马程序员-java 概述与基础知识 1.何为编程? 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果 的过程. 为了使 ...

最新文章

  1. java四种xml_Java中四种XML解析技术
  2. 有一种尴尬,叫大厂中层
  3. java面试基础问题积累----多线程,并发
  4. Python(数据库之表操作)
  5. 我给媳妇解释设计模式:第一部分
  6. VTK:图片之DrawShapes
  7. NBear.Mapping使用教程(5):实体对象与NameValueCollection,Dicitonary以及NBear.Mapping性能
  8. python3 抓取图片
  9. 目前8岁女儿上的课程
  10. jQuery动态网址标签
  11. CentOS7自行搭建KMS服务器
  12. 融云 java_融云开发者文档
  13. 循环 计算机英语,计算机英语词汇解释
  14. 水滴pin安卓版apk_水滴清单app
  15. C++源代码单词扫描程序(词法分析)
  16. 公众号文章中怎样添加音乐、音频
  17. hdu 1568 Fibonacci(fibonacci通项+对数性质)
  18. 戴尔 Precision 5470 25 周年纪念款笔记本 评测
  19. rockchip rk3368(px5)车载开发之路1,原生代码系统正常启动
  20. pdf中如何更改文字的颜色

热门文章

  1. 【ssh】工作原理、sshpass超详细介绍
  2. 我的世界pvp代码大全
  3. 初学python 对象数组转JSON
  4. 任务驱动教学法在JAVA教学中的问题和策略
  5. 分析占用了大量 CPU 处理时间的是Java 进程中哪个线程
  6. html 输入框输入事件,input输入框事件
  7. JSONDecodeError: Expecting Value: Line * column * (char *)
  8. js同步和异步的区别
  9. gta5服务器多久维护,各位大佬问一下GTA5 股票里的BAWSAQ为什么一直维护啊
  10. 【uni-app】菜菜的我xie了一个电池电量组件