带你了解常见的编码表,以及他们自己的关系.

一:ASCII 

      世界上虽然有各种各样的字符,但计算机发明之初没有考虑那么多,基本上只考虑了美国的需求,美国大概只需要128个字符,美国就规定了这128个字符的二进制表示方法,这个方法是一个标准,称为ASCII编码,全称是American Standard Code for Information Interchange,美国信息互换标准代码。128个字符用7个位刚好可以表示,计算机存储的最小单位是byte,即8位,ASClI码中最高位设置为O,用剩下的7位表示字符。这7位可以看做数字0到127,ASCII码规定了从0到127个,每个数字代表什么含义。我们先来看数字32到126的含义,如下图所示,除了中文之外,我们平常用的字符基本都涵盖了,键盘上的字符大部分也都涵盖了。

注意: 数字32到126表示的这些字符都是可打印字符,0到31和127表示一些不可以打印的字符,这些字符一般用于控制目的,这些字符中大部分都是不常用的,下表列出了其中相对常用的字符。

举一个例子:

package com.itheima. stringDemo;public class Demo1 {public static void main(String[] args) {char c = 9;System.out.print(c);System.out. println(黑马");}
}

编译结果:

Asci码对美国是够用了,但对别的国家而言却是不够的,于是,各个国家的各种计算机厂商就发明了各种各样的编码方式以表示自己国家的字符,为了保持与Ascii码的兼容性,一般都是将最高位设置为1。也就是说,当最高位为O时,表示Ascii码,当为1时就是各个国家自己的字符。在这些扩展的编码中,在西欧国家中流行的是ISO 8859-1和Windows-1252,在中国是GB2312,GBK,GB18030和Big5,我们逐个来研究这些编码。

二: ISO 8859-1

               ISO 8859-1又称Latin-,它也是使用一个字节表示一个字符,因为西欧的文字也都是字母拼接,只不过不是26个英文字母罢了,其中0到127与Asci—样,128到255规定了不同的含义。在128到255中,128到159表示一些控制字符,这些字符也不常用,就不介绍了。160到255表示一些西欧字符,如下图所示:

 三: windows-1252

       IS0 8859-1虽然号称是标准,用于西欧国家,但它连欧元(C)这个符号都没有,因为欧元比较晚,而标准比较早。实际使用中更为广泛的是Windows-1252编码,这个编码与ISO8859-1基本是一样的,区别只在于数字128到159,Windows-1252使用其中的一些数字表示可打印字符,这些数字表示的含义,如下图所示:;

注意: 这个编码中加入了欧元符号以及一些其他常用的字符。基本上可以认为,ISO8859-1已被Windows-1252取代,在很多应用程序中,即使文件声明它采用的是ISO 8859-1编码,解析的时候依然被当做Windows-1252编码。

四:  GB2312

       美国和西欧字符用一个字节就够了,但中文显然是不够的。中文第一个标准是GB2312。GB23.1.2标准主要针对的是简体中文常见字符,包括约7000个汉字,不包括一些罕见词,不包括繁体字。GB2312固定使用两个字节表示汉字,在这两个字节中,最高位都是1,如果是0,就认为是Ascii字符。在这两个字节中,其中第一个字节范围是1010 0001(十进制161)-11110111(十进制247),第二个字节范围是10100001(十进制1611-11111110(十进制254)。
比如,"贤哥"的GB2312编码是

 五: GBK

      GBK建立在GB2312的基础上,向下兼容GB231.2,也就是说,GB231.2编码的字符的二进制表示,在GBK编码里是完全一样的。GBK增加了一万四千多个汉字,共计约21000汉字,其中包括繁体字。GBK同样使用固定的两个字节表示,其中第一个字节范围是1000 0001(十进制129)- 11111110(十进制254),第二个字节范围是01000000(十进制64)-01111110(十进制126)和1000 0000(十进制128)-11111110(十进制254)。
       疑问: 需要注意的是,第二个字节是从64开始的(64属于byte正数范围,和ASCII的编码重合了),也就是说,第二个字节最高位可能为0。那怎么知道它是汉字的一部分,还是一个ASCII字符呢?
       其实很简单,因为汉字是用固定两个字节表示的,在解析二进制流的时候,如果第一个字节的最高位为1,那么就将下一个字节读进来一起解析为一个汉字,而不用考虑它的最高位,解析完后,跳到第三个字节继续解析。

六: GB18030

       GB18030向下兼容GBK,增加了五万五千多个字符,共七万六千多个字符。包括了很多少数民族字符,以及中日韩统一字符。用两个字节已经表示不了GB18030中的所有字符,GB18030使用变长编码,有的字符是两个字节,有的是四个字节。在两字节编码中,字节表示范围与GBK一样。在四字节编码中,第一个字节的值从10000001(十进制129)到11111110(十进制254),第二个字节的值从0011 0000(十进制48)到00111001(十进制57),第三个字节的值从1000 0001(十进制129)到11111110(十进制254),第四个字节的值从0011 0000(十进制48)到0011 1001(十进制57)。

       疑问: 解析二进制时,如何知道是两个字节还是四个字节表示一个字符呢?

        很简单,看第二个字节的范围,如果是48到57就是四个字节表示,因为两个字节编码中第二字节都比这个大所以这样综合说明GB18030兼容GBK,兼容GB2312,兼容ASCII,但是GB18030,GBK,GB2312这三个编码和S08859-1是不兼容的哦

七: Big5

        Big5是针对繁体中文的,广泛用于台湾香港等地。Big5包括1万3千多个繁体字,和GB2312类似,一个字符同样固定使用两个字节表示。在这两个字节中,第一个字节范围是10000001(十进制129)到11111110(十进制254),第二个字节范围是0100 0000(十进制64)-01111110(十进制126)和1010 0001(十进制161)-11111110(十进制254)。Big5和GB18030,GBK,GB2312不兼容哈,如果已经理解了上文,其实你就能理解为什么Big5和GB的三个编码为什么不兼容了。

编码表汇总 

      我们简单汇总一下上面的内容。Ascii码是基础,一个字节表示,最高位设为O,其他7位表示128个字符。其他编码都是兼容Ascii的,最高位使用1来进行区分。西欧主要使用Windows-1252,使用一个字节,增加了额外128个字符。中文大陆地区的三个主要编码GB2312,GBK,GB18030,有时间先后关系,表示的字符数越来越多,且后面的兼容前面的,GB2312和GBK都是用两个字节表示,而GB18030则使用两个或四个字节表示。香港台湾地区的主要编码是Big5。
       如果文本里的字符都是Ascii码字符,那么采用以上所说的任一编码方式都是一样的,不会乱码。但如果有高位为1的字符,除了GB2312/GBK/GB18030外,其他编码都是不兼容的,比如,Windows-1252和中文的各种编码是不兼容的,即使Big5和GB18030都能表示繁体字,其表示方式也是不一样的,而这就会出现所谓的乱码。

乱码和兼容

兼容: GB2312[GBK/GB18030 ASCII是兼容的比如我们文本里面a字符,使用这四种码表任何一种都是可以正常显示的。

windows-1252和ISO-8859-1和ASCII是兼容的

Big5和ASClI是兼容的


但是西欧编码和Big5以及GB系列的编码他们相互之间是不兼容的,也就是同样的码值在三种编码表中显示的内容是不一样的。

 

八: Unicode

        以上我们介绍了中文和西欧的字符与编码,但世界上还有很多的国家的字符,每个国家的各种计算机厂商都对自己常用的字符进行编码,在编码的时候基本忽略了别的国家的字符和编码,甚至忽略了同一国家的其他计算机 厂商,这样造成的结果就是,出现了太多的编码,且互相不兼容。
       问: 世界上所有的字符能不能统─编码呢?可以,这就是Unicode。
Unicode做了一件事,就是给世界上所有字符都分配了一个唯一的数字编号,这个编号范围从Qx000000到Ox10EFFEE,包括110多万。但大部分常用字符都在0x0000到OXFFEE之间,即65536个数字之内。每个字符都有一个Unicode编号,这个编号一般写成16进制,在前面加U+。大部分中文的编号范围在U+4EO0到U+9FA5,例如,"贤"的Unicode是U+8D24。
       Unicode就做了这么一件事,就是给所有字符分配了唯一数字编号。它并没有规定这个编号怎么对应到二进制表示,这是与上面介绍的其他编码不同的,其他编码都既规定了能表示哪些字符,又规定了每个字符对应的二进制是什么,而Unicode本身只规定了每个字符的数字编号是多少。

Unicode发展历程:


        Unicode其实应该是一个码值表。Unicode的作用是为每一个字符提供一个唯一的数字码,而对数字码的存储规则的定义则需要依靠UTF-8/UTF-16/UTF-32,UTF-8/UTF-16/UTF-32是通过对Unicode码值进行对应规则转换后,编码保持到内存/文件中。UTF-8/UTF-16都是可变长度的编码方式。
那编号怎么对应到二进制表示呢? 有多种方案,主要有UTF-32,UTF-16和UTF-8。

 详图

 疑问: 为什么不直接把Unicode码值直接存储到内存当中?

答:  因为Unicode表示范围Qx000000到Ox10EFFEE表示的所有数要3个字节,但是3个字节太浪费了,很多字符表示起来根本不需要3个字符,所有太浪费资源了.计算机的内存资源是非常宝贵的.

后面的UTF-32/UTF-16/UTF-8详解就请看:https://blog.csdn.net/m0_50370837/article/details/118862040
 

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注