字符编码

这里介绍下编码类型的概念和之间的关系。如ASCII,IOS-8859-1,GB2312,GBK,Unicode,UTF-8等。

 所有的信息最终都表示为一个二进制的字符串,每一个二进制位(bit)有0和1两种状态。
我们需要把字符’A’存入计算机时,就是需要一个规则。这个规则可以将字符映射到唯一的一种状态(二进制字符串),这就是编码。在ASCII编码规则中,字符’A’对应的是01000001。

ASCII

 这套编码规则是由美国定制,一共规定了128个字符的编码,这128个符号,只占用了一个字节(8 bit)的后面7位,最前面的1位统一规定为0。总共才有128个字符编码,一个字节都没有用完,这好像似乎有点太少了。
于是乎,就开始压榨最高位,对其为1时也进行编码,利用最高位进行编码的方式就称为非ASCII编码,如ISO-8859-1编码。

ISO-8859-1

 ISO-8859-1编码由ISO组织指定,是在ASCII码基础上又制定了一些标准用来扩展ASCII编码。其中 00000000(0) ~ 01111111(127) 与ASCII的编码一样,并对 10000000(128) ~ 11111111(255) 这一段进行了编码。
ISO-8859-1编码也是单字节编码,最多能够表示256个字符。Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。
但即使能够表示256个字符,对中文而言还是太少了,一个字节肯定不够,必须用多个字节表示。但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候仍旧使用 ISO8859-1编码来表示。而且在很多协议上,默认使用该编码。

GB2312

 GB2312编码是第一个汉字编码国家标准。GB2312编码共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。同时,GB2312编码收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。
GB2312是双字节编码,其中高字节表示区,低字节表示位。
GB2312其对所收录字符进行了”分区”处理,共94个区,区从1(十进制)开始,一直到94(十进制),每区含有94个位,位从1(十进制)开始,一直到94(十进制),共8836(94 * 94)个码位,这种表示方式也称为区位码。各区具体说明如下:

  • 01-09区收录除汉字外的682个字符,有164个空位(9 * 94 - 682)。
  • 10-15区为空白区,没有使用
  • 16-55区收录3755个一级汉字(简体),按拼音排序。
  • 56-87区收录3008个二级汉字(简体),按部首/笔画排序。
  • 88-94区为空白区,没有使用。

举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601。

GB2312规定对收录的每个字符采用两个字节表示,第一个字节为“高字节”,对应94个区;第二个字节为“低字节”,对应94个位。所以它的区位码范围是:0101-9494。
区号和位号分别加上0xA0就是GB2312编码。例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。
GB2312编码范围:A1A1-FEFE,其中汉字的编码范围为B0A1-F7FE,第一字节0xB0-0xF7(对应区号:16-87),第二个字节0xA1-0xFE(对应位号:01-94)。

区位码转换为GB2312编码规范

还有一些汉字在GB2312中没有被编码,这样就导致了问题,随之就出现了主流的GBK编码。在讲解GBK编码之前,我们另外讲解一下BIG5编码。

BIG5

 BIG5编码又称大五码,是繁体中文字符集编码标准,共收录13060个中文字,其中有二字为重复编码。
BIG5采用双字节编码,使用两个字节来表示一个字符。高位字节使用了0x81-0xFE,低位字节使用了0x40-0x7E,及0xA1-0xFE。

GBK

 是对GB2312编码的扩充,完全兼容GB2312编码。但其不兼容BIG5编码。GBK对汉字采用双字节编码。GBK字符集共收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。
相比于GB2312编码,GBK编码了更多汉字,如’镕’字。
GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 码位。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。

Unicode

 国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。
Unicode是指一张表,里面包含了可能出现的所有字符,每个字符对应一个数字,这个数字称为码点(Code Point),如字符’H’的码点为72(十进制),字符’李’的码点为26446(十进制)。Unicode表包含了1114112个码点,即从000000(十六进制) - 10FFFF(十六进制)。地球上所有字符都可以在Unicode表中找到对应的唯一码点。
Unicode将码空间划分为17个平面,从00 - 10(十六进制,最高两位),即从0 - 16(十进制),每个平面有65536个码点(2^16),其中最重要的是第一个Unicode平面(码位从0000 - FFFF),包含了最常用的字符,该平面被称为基本多语言平面(Basic Multilingual Plane),缩写为BMP,其他平面称为辅助平面(Supplementary Planes),在基本多文种平面內, 从D800到DFFF之间的码位区段是永久保留不映射到字符的, 因此UTF-16编码巧妙的利用了这保留下来的码位来对辅助平面内的字符进行编码。
 Unicode只是一个符号集,只规定的字符所对应的码点,并没有指定如何存储,如何进行存储出现了不同的编码方案,关于Unicode编码方案主要有两条主线:UCS和UTF。UTF主线由Unicode Consortium进行维护管理,UCS主线由ISO/IEC进行维护管理。

UTF

UTF全称为”Unicode Transformation Format”,在UTF中主要有UTF-8,UTF-16和UTF-32。

UTF-8

 UTF-8是一种变长编码方式,使用1-4个字节进行编码。UTF-8完全兼容ASCII,对于ASCII中的字符,UTF-8采用的编码值跟ASCII完全一致。UTF-8是Unicode一种具体的编码实现。UTF-8是在互联网上使用最广的一种Unicode的编码规则,因为这种编码有利于节约网络流量(因为变长编码,而非统一长度编码)。

Unicode码点转化为UTF-8编码的规则如下:

  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
  2. 对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

如图:

示例:
字符’A’的Unicode码点为65(十进制),根据上表,在第一行范围,则字符’A’的UTF-8编码为01000001。
中文字符’李’的Unicode码点为26446(十进制),二进制为01100111 01001110,十六进制为674E。根据上表,在第三行范围,则将’李’二进制代码从低位到高位依次填入x中,不足的填入0。得到UTF-8编码为11100110 10011101 10001110,即E69D8E(十六进制)。

由上述编码规则可知,0000 0000 - 0000 FFFF(第一行到第三行)为Unicode第一个平面(基本多语言平面),而0001 0000 - 10 FFFF(第四行)为Unicode其他平面(辅助平面)。在基本多语言平面对应了绝大多数常用的字符。对于大于65535(十进制)的码点,即在辅助平面上的码点,需要使用4个字节来进行UTF-8编码。
UTF-8编码不需要BOM机制
因为在UTF-8编码中,其自身已经带了控制信息,如1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx,其中1110就起到了控制作用,所以不需要额外的BOM机制。

UTF-16 UTF-32

UTF-8是不定长的编码,使用1、2、3、4个字节编码,而UTF-16则只使用2或4个字节编码。UTF-16也是Unicode一种具体的编码实现。
UTF-32是使用4个字节表示,也采用BOM机制。

UCS

UCS全称为”Universal Character Set”,在UCS中主要有UCS-2和UCS-4。

UCS-2

UCS-2是定长字节的,固定使用2个字节进行编码,从0000(十六进制)- FFFF(十六进制)的码位范围,对应第一个Unicode平面。采用BOM(Byte Order Mark)机制,该机制作用如下:1. 确定字节流采用的是大端序还是小端序。2. 确定字节流的Unicode编码方案。

UCS-4

UCS-4是定长字节的,固定使用4个字节进行编码。也采用了BOM机制。

GBK和UTF-8的区别

  1. GBK编码专门用来解决中文编码的,是双字节的。不论中英文都是双字节的。外国人看会出现乱码,此为我中华为自己汉字编码而形成之解决方案。
  2. UTF-8 编码是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。但是外国人看的话不会乱码,此为西人为了解决多字节字符而形成之解决方案。
  3. GBK包含全部中文字符,UTF-8则包含全世界所有国家需要用到的字符。
  4. UTF-8编码的文字可以在各国各种支持UTF8字符集的浏览器上显示。比如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,而无需他们下载IE的中文语言支持包。
  5. UTF8是国际编码,它的通用性比较好,外国人也可以浏览论坛,GBK是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大。
  6. 如果你主要做中文程序的开发,客户也主要是中国人的话就用GBK吧,因为UTF-8编码的中文使用了三个字节,用GBK节省了空间。
  7. 如果做英文网站开发,还是用utf-8吧,因为utf-8中英文只占一个字节。GBK中英文也是两个字节的,并且国外客户访问GBK要下载语言包。
  8. 如果你的网站是中文的,但国外用户也不少,最好也用UTF-8的吧。