您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > 2Unicode的编码和实现
2Unicode的编码和实现.txt如果你同时爱几个人,说明你年轻;如果你只爱一个人,那么,你已经老了;如果你谁也不爱,你已获得重生。积极的人一定有一个坚持的习惯。大概来说,Unicode编码系统可分为编码方式和实现方式两个层次。1.编码方式Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。Unicode字符集可以简写为UCS(UnicodeCharacterSet)。早期的Unicode标准有UCS-2、UCS-4的说法。UCS-2用两个字节编码,UCS-4用4个字节编码。UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个平面(plane)。每个平面根据第3个字节分为256行(row),每行有256个码位(cell)。group0的平面0被称作BMP(BasicMultilingualPlane)。将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。每个平面有2^16=65536个码位。Unicode计划使用了17个平面,一共有17*65536=1114112个码位。在Unicode5.0.0版本中,已定义的码位只有238605个,分布在平面0、平面1、平面2、平面14、平面15、平面16。其中平面15和平面16上只是定义了两个各占65534个码位的专用区(PrivateUseArea),分别是0xF0000-0xFFFFD和0x100000-0x10FFFD。所谓专用区,就是保留给大家放自定义字符的区域,可以简写为PUA。平面0也有一个专用区:0xE000-0xF8FF,有6400个码位。平面0的0xD800-0xDFFF,共2048个码位,是一个被称作代理区(Surrogate)的特殊区域。代理区的目的用两个UTF-16字符表示BMP以外的字符。在介绍UTF-16编码时会介绍。如前所述在Unicode5.0.0版本中,238605-65534*2-6400-2408=99089。余下的99089个已定义码位分布在平面0、平面1、平面2和平面14上,它们对应着Unicode目前定义的99089个字符,其中包括71226个汉字。平面0、平面1、平面2和平面14上分别定义了52080、3419、43253和337个字符。平面2的43253个字符都是汉字。平面0上定义了27973个汉字。2.实现方式在Unicode中:汉字“字”对应的数字是23383。在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCSTransformationFormat”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是:BYTEdata_utf8[]={0xE6,0xB1,0x89,0xE5,0xAD,0x97};//UTF-8编码WORDdata_utf16[]={0x6c49,0x5b57};//UTF-16编码DWORDdata_utf32[]={0x6c49,0x5b57};//UTF-32编码这里用BYTE、WORD、DWORD分别表示无符号8位整数,无符号16位整数和无符号32位整数。UTF-8、UTF-16、UTF-32分别以BYTE、WORD、DWORD作为编码单位。“汉字”的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个WORD,大小是4个字节。“汉字”的UTF-32编码需要两个DWORD,大小是8个字节。根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。下面介绍UTF-8、UTF-16、UTF-32、字节序和BOM。UTF-8UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:Unicode编码(16进制)║UTF-8字节流(二进制)000000-00007F║0xxxxxxx000080-0007FF║110xxxxx10xxxxxx000800-00FFFF║1110xxxx10xxxxxx10xxxxxx010000-10FFFF║11110xxx10xxxxxx10xxxxxx10xxxxxxUTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。例1:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx10xxxxxx10xxxxxx。将0x6C49写成二进制是:0110110001001001,用这个比特流依次代替模板中的x,得到:111001101011000110001001,即E6B189。例2:Unicode编码0x20C30在0x010000-0x10FFFF之间,使用用4字节模板了:11110xxx10xxxxxx10xxxxxx10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):000100000110000110000,用这个比特流依次代替模板中的x,得到:11110000101000001011000010110000,即F0A0B0B0。UTF-16UTF-16编码以16位无符号整数为单位。我们把Unicode编码记作U。编码规则如下:如果U0x10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。如果U≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyyyyyyyyxxxxxxxxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy110111xxxxxxxxxx。为什么U'可以被写成20个二进制位?Unicode的最大码位是0x10ffff,减去0x10000后,U'的最大值是0xfffff,所以肯定可以用20个二进制位表示。例如:Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:00010000110000110000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:11011000010000111101110000110000,即0xD8430xDC30。按照上述规则,Unicode编码0x10000-0x10FFFF的UTF-16编码有两个WORD,第一个WORD的高6位是110110,第二个WORD的高6位是110111。可见,第一个WORD的取值范围(二进制)是1101100000000000到1101101111111111,即0xD800-0xDBFF。第二个WORD的取值范围(二进制)是1101110000000000到1101111111111111,即0xDC00-0xDFFF。为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):D800-DB7F║HighSurrogates║高位替代DB80-DBFF║HighPrivateUseSurrogates║高位专用替代DC00-DFFF║LowSurrogates║低位替代高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。那么,高位专用替代是什么意思?我们来解答这个问题,顺便看看怎么由UTF-16编码推导Unicode编码。如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间,那么它的Unicode编码在什么范围内?我们知道第二个WORD的取值范围是0xDC00-0xDFFF,所以这个字符的UTF-16编码范围应该是0xDB800xDC00到0xDBFF0xDFFF。我们将这个范围写成二进制:11011011100000001101110000000000-11011011111111111101111111111111按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到11100000000000000000-11111111111111111111即0xe0000-0xfffff,按照编码的相反步骤再加上0x10000,得到0xf0000-0x10ffff。这就是UTF-16编码的第一个WORD在0xdb80到0xdbff之间的Unicode编码范围,即平面15和平面16。因为Unicode标准将平面15和平面16都作为专用区,所以0xDB80到0xDBFF之间的保留码位被称作高位专用替代。UTF-32UTF-32编码以32位无符号整数为单位。Unicode的UTF-32编码就是其对应的32位无符号整数。字节序根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。例如:Unicode编码║UTF-16LE║UTF-16BE║UTF32-LE║UTF32-BE0x006C49║496C║6C49║496C0000║00006C490x020C30║43D830DC║D843DC30║300C0200║00020C30那么,怎么判断字节流的字节序呢?Unicode标准建议用BOM(ByteOrderMark)来区分字节序,即在传输字节流前,先传输被作为BOM的字符零宽无中断空格。这个字符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定义的码位,不应该出现在实际传输中。下表是各种UTF编码的BOM:UTF编码║ByteOrderMarkUTF-8║EFBBBFUTF-16LE║FFFEUTF-16BE║FEFFUTF-32LE║FFFE0000UTF-32BE║0000FEFF
本文标题:2Unicode的编码和实现
链接地址:https://www.777doc.com/doc-2914295 .html