仔细读读字符集(Unicode、ASCII、GB2312)和字符编码(GB2310、UTF-8、UTF-16、GBK、)和转换规则

首先弄明白几个概念:
字符(Character):在计算机和电信技术中,一个字符是一个单位的字形、类字形单位或符号的基本信息,字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等,例如:A,B,1,2,&,%等这些都称为字符。
字符集(Character set):是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,例如:ASCII字符集、GB2312字符集,unicode字符集等
字符编码(Character encoding)也称字集码,是把字符集中的字符编码为指定集合中某一对象(例如: 比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。也就是说字符编码是一套法则,将字符集中的每一个字符,映射为 另一个集合(比特模式、自然数序列、8位组或者电脉冲)中。

字符集和字符编码的关系,以ASCII来说就是:A->0x01000001,B->0x01000010…… 即将字符集中每一个字符对应一个比特序列

为什么会有这么多字符集呢和字符编码呢?
这个原因很简单,不同的国家一般都有自己的文字和符号,ASCII只能满足一些一些英语国家的需要,其他的国家当然需要自己的字符集来表示自己的文字,于是有了不同的字符集和编码。
GB2312字符集和编码:
GB2312-80全称是《信息交换用汉字编码字符集·基本集》是由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准。基本集 共收入汉字6763个和非汉字图形字符682个。整个字符集分成94个区,每区有94个位。每个区位上只有一个字符,因此可用所在的区和位来对汉字进行编 码,称为区位码。
把换算成十六进制的区位码加上2020H,就得到国标码。国标码加上8080H,就得到常用的计算机机内码。
为什么要加2020H呢?
    因为ASCII码编码中分控制信号编码和有型字符编码,前32个是控制码,如回车、换行、退格等,为避开这些控制码,国标码规定在区位码的基础上加20H(即32的16进制数)
为什么要加上8080H呢?
   是因为在计算机中ASCII码和汉字机内码是共存的,那么我们就要来区分它们,我们知道ASCII码的最高位是0,所以我们将汉字机内码的最高位置为1, (80H二级制表示就为10000000)表示区别所以计算机在判断ASCII码还是汉字机内码的时候,只需要判断它们的最高位就行了

GBK(Chinese Internal Code Specification)全称《汉字内码扩展规 范》,是对GB2312编码的扩展,因此完全兼容GB2312-80标准。GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。

中国自己搞了一套编码,其他国家当然也各自做了自己的编码,这样在本地自己使用是没有问题的,一旦在网络上传输,就会出现各种乱码,也就是我们常见的?????????等等
于是Unicode字符集和编码出现了。

Unicode编码:
Unicode 是基于通用字符集UCS(Universal Character Set)的标准来发展,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。Unicode实际上 是一个字符集。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可 以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
在Unicode字符集中的某个字符对应的代码值,称作代码点(CodePoint),用16进制书写,并加上U+前缀。 Unicode定义的字符集已经超过16位所能表达的范围,把所有这些CodePoint分成17个代码平面(Code Plane)
U+0000 ~ U+FFFF划入基本多语言平面(Basic MultilingualPlane,简记为BMP);
其余划入16个辅助平面(Supplementary Plane),代码点范围U+10000 ~ U+10FFFF。


UTF-8:采用变长字节 (1 ASCII, 2 希腊字母, 3 汉字, 4 平面符号) 表示,网络传输, 即使错了一个字节,不影响其他字节,而双字节只要一个错了,其他也错了,具体如下:
如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的字节数,其余各字节均以10开头。UTF-8最多可用到6个字节。

将UTF8对Unicode编码的方式如下:
单字节:0xxxxxxx
双字节:110xxxxx 10xxxxxx  
三字节:1110xxxx 10xxxxxx 10xxxxxx
四字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
例如"汉"字的Unicode编码是6C49。6C49在0800-FFFF之间,所以要用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 1100 0100 1001,将这个比特流按三字节模板的分段方法分为0110 110001 001001,依次代替模板中的x,得到:1110-0110 10-110001 10-001001,即E6 B1 89,这就是其UTF8的编码。

这里说下:一般采用三种方式来决定文本的字符集和编码:
1.检测文件头标识,2.提示用户选择,3.根据一定的规则猜测
最标准的途径是检测文本最开头的几个字节,开头字节 Charset/encoding,如下表:
EF BB BF UTF-8
FE FF UTF-16/UCS-2, little endian
FF FE UTF-16/UCS-2, big endian
FF FE 00 00 UTF-32/UCS-4, little endian.
00 00 FE FF UTF-32/UCS-4, big-endian.

UTF-16
UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节 (2字节) 储存,但UTF-16却无法兼容于ASCII编码。
UTF-16编码以16位无符号整数为单位。注意是16位为一个单位,不表示一个字符就只有16位。现在机器上的unicode编码一般指的就是UTF- 16。绝大部分2个字节就够了,但是不能绝对的说所有字符都是2个字节。这个要看字符的unicode编码处于什么范围而定,可能是2个字节,也可能是4 个字节。所以要决定UTF-8或UTF-16哪种编码比较有效率,还要视所使用的字符的分布范围而定
对U+0000.. U+D7FF以及U+E000.. U+FFFF的编码
UTF-16与UCS-2对这个范围内的CodePoint进行编码,采用单个16bit长的CodeUnit,数值等价于对应的Code Point。BMP中的这些Code Point是仅有的可以被UCS-2表示的Code Point。
对U+10000.. U+10FFFF的编码 辅助平面(Supplementary Planes)中的CodePoint,在UTF-16中被编码为一对16bit长的Code Unit(即32bit,4Bytes),称作代理对(surrogate pair)。

UTF-16辅助平面代理对与Unicode的对应关系如下表:

Lead \ Trail 0xDC00  0xDC01  …  0xDFFF
0xD800 U+10000 U+10001 U+103FF
0xD801 U+10400 U+10401  U+107FF
0xDBFF  U+10FC00  U+10FC01  U+10FFFF

具体编码方式:

1.Code Point减去0x10000, 得到的值是长度为20bit(0..0xFFFFF);
2.由1得到数值的高位的10比特的值(值范围为0..0x3FF)加上0xD800得到第一个Code Unit或称作高位代理(high surrogate)或前导代理(lead surrogate)。取值范围是0xD800..0xDBFF。
3.由1得到数值的低位的10比特的值(值范围为0..0x3FF)加上0xDC00得到第二个Code Unit或称作低位代理(low surrogate)或后尾代理(trail surrogate)。取值范围是0xDC00..0xDFFF。
这样,这个范围内的字符就被编码成了一个代理对[lead surrogate,trail surrogate]:两个16bits的Code Unit,取值范围分别是0xD800..0xDBFF和0xDC00..0xDFFF。而BMP中得到的Code Unit的范围是0x0000..0xFFFF(0xD800..0xDFFF是保留的,不包含其中),所以这三个区段是相互不重叠的,在解码时很容易实 现。
UTF-16解码[高位代理+低位代理]得到的Code Unit对与Code Point的对应关系如上表所示。


UTF-32
UTF-32和Unicode码表基本一一对应,固定四个字节。但是如果统一用4个字节,占用空间太浪费,UTF-32通常会是其它编码的二到四倍

Pingbacks are open.

Trackback URL

Comments

0 Comments

Post your comment

cancel reply