Unicode详解

最近一直在忙点私活,又好久没写blog了,再不写点的话二月份就又要以单篇文章结束了。 前一阵子一直在研究Unicode,索性把研究结果介绍一下吧。

可能大家都听说过 Unicode、UCS-2、UTF-8 等等词汇,但它们具体是什么意思, 是什么原理,之间有什么关系,恐怕就很少有人明白了。 下面就分别介绍一下它们。


基本知识

介绍Unicode之前,首先要讲解一些基础知识。虽然跟Unicode没有直接的关系, 但想弄明白Unicode,没这些还真不行。

字节和字符的区别

咦,字节和字符能有什么区别啊?不都是一样的吗?完全正确,但只是在古老的DOS时代。 当Unicode出现后,字节和字符就不一样了。

字节(octet)是一个八位的存储单元,取值范围一定是0~255。而字符(character,或者word) 为语言意义上的符号,范围就不一定了。例如在UCS-2中定义的字符范围为0~65535, 它的一个字符占用两个字节。

Big Endian和Little Endian

上面提到了一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢? 比如字符0xabcd,它的存储格式到底是 AB CD,还是 CD AB 呢?

实际上两者都有可能,并分别有不同的名字。如果存储为 AB CD,则称为Big Endian; 如果存储为 CD AB,则称为Little Endian

具体来说,以下这种存储格式为Big Endian,因为值(0xabcd)的高位(0xab)存储在前面:

地址
0×00000000AB
0×00000001CD

相反,以下这种存储格式为Little Endian:

地址
0×00000000CD
0×00000001AB

UCS-2和UCS-4

Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值, 这个值称为代码点(code point)。代码点的值通常写成 U+ABCD 的格式。 而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。 顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000~U+FFFF。

为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。 它的范围为 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是一样的。

要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。 规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。

UTF-16和UTF-32

UTF-16

UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。

不难猜到,UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式 直接保存下来。UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。

UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符 来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。

其实BOM是个小聪明的想法。由于UCS-2没有定义U+FFFE, 因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF, 并且可以判断出是Big Endian还是Little Endian。

举个例子。“ABC”这三个字符用各种方式编码后的结果如下:

UTF-16BE 00 41 00 42 00 43
UTF-16LE 41 00 42 00 43 00
UTF-16(Big Endian) FE FF 00 41 00 42 00 43
UTF-16(Little Endian) FF FE 41 00 42 00 43 00
UTF-16(不带BOM) 00 41 00 42 00 43

Windows平台下默认的Unicode编码为Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。 你可以打开记事本,写上ABC,然后保存,再用二进制编辑器看看它的编码结果。

notepad-encode.png

另外,UTF-16还能表示一部分的UCS-4代码点——U+10000~U+10FFFF。 表示算法比较复杂,简单说明如下: 1. 从代码点U中减去0×10000,得到U’。这样U+10000~U+10FFFF就变成了 0×00000~0xFFFFF。 2. 用20位二进制数表示U’。 U’=yyyyyyyyyyxxxxxxxxxx 3. 将前10位和后10位用W1和W2表示,W1=110110yyyyyyyyyy,W2=110111xxxxxxxxxx,则 W1 = D800~DBFF,W2 = DC00~DFFF。

例如,U+12345表示为 D8 08 DF 45(UTF-16BE),或者08 D8 45 DF(UTF-16LE)。

但是由于这种算法的存在,造成UCS-2中的 U+D800~U+DFFF 变成了无定义的字符。

UTF-32

UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代码点,而无需像UTF-16那样使用复杂的算法。 与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三种编码,UTF-32也同样需要BOM字符。 仅用’ABC’举例:

UTF-32BE 00 00 00 41 00 00 00 42 00 00 00 43
UTF-32LE 41 00 00 00 42 00 00 00 43 00 00 00
UTF-32(Big Endian) 00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43
UTF-32(Little Endian) FF FE 00 00 41 00 00 00 42 00 00 00 43 00 00 00
UTF-32(不带BOM) 00 00 00 41 00 00 00 42 00 00 00 43

UTF-8

UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节, 这样在表示纯ASCII文件时会有很多00字节,造成浪费。 而RFC3629定义的UTF-8则解决了这个问题。

UTF-8用1~4个字节来表示代码点。表示方式如下:

UCS-2 (UCS-4)位序列 第一字节第二字节第三字节第四字节
U+0000 .. U+007F00000000-0xxxxxxx0xxxxxxx
U+0080 .. U+07FF00000xxx-xxyyyyyy110xxxxx10yyyyyy
U+0800 .. U+FFFFxxxxyyyy-yyzzzzzz1110xxxx10yyyyyy10zzzzzz
U+10000..U+10FFFF00000000-000wwwxx-&br;xxxxyyyy-yyzzzzzzz11110www10xxxxxx10yyyyyy10zzzzzz

可见,ASCII字符(U+0000~U+007F)部分完全使用一个字节,避免了存储空间的浪费。 而且UTF-8不再需要BOM字节。

另外,从上表中可以看出,单字节编码的第一字节为[00-7F],双字节编码的第一字节为[C2-DF], 三字节编码的第一字节为[E0-EF]。这样只要看到第一个字节的范围就可以知道编码的字节数。 这样也可以大大简化算法。

Unicode详解》上有 41 条评论

  1. 很不错,简单明了,而又切中要害,转载一下

  2. 很好,我在学习本地化的桌面排版,刚好要了解下unicode.谢了

  3. 很不错 挺全面的!支持!!

  4. 很不错,清晰明了。 不过,应该文章应该指出“FF FE ”是指Little Endian。

  5. Pingback 引用通告: 方位志 » Blog Archive » Unicode详解

  6. 不错不错,学了许多东西,不过有一点点东西到现在还没有看懂。

  7. 例子充分,简单易懂,很不错!学习了

  8. 双字节编码的第一字节为[C0-DF]吧。

  9. 22

    是的,双字节第一字节为 110xxxxx,即11000000-11011111,即C0-DF。

  10. 而且UTF-8不再需要BOM字节。 ⇒哈哈,楼主太绝对了吧! 前几天,我用java从数据库读出一个大的String,把这个String作为新建的csv文件的内容。String里面是中日英三种语言的。如果只是用UTF-8的话,Notepad++这种工具打开没问题,单用excel打开就乱码了。好像是因为excel默认的utf8文件是带bom的,所以我就在String前面加上了BOM,结果就全部工具打开全OK了~~~

  11. 而且UTF-8不再需要BOM字节。 ⇒哈哈,楼主太绝对了吧! 前几天,我用java从数据库读出一个大的String,把这个String作为新建的csv文件的内容。String里面是中日英三种语言的。如果只是用UTF-8的话,Notepad++这种工具打开没问题,单用excel打开就乱码了。好像是因为excel默认的utf8文件是带bom的,所以我就在String前面加上了BOM,结果就全部工具打开全OK了~~~ ==》 用notepad保存的时候选择utf-8编码格式,用ultraedit查看,的确是没有bom的

  12. 楼主,你在UTF-8这一节的表格中,最后一行代码点的范围你写成:U+10000..U+1FFFFF

    但我查了资料,似乎应该是:U+10000..U+10FFFF

    请指正。

  13. @jinhr 谢谢你的指正,的确应该是U+10FFFF。已经改正了。

  14. 很有收获 如果单从易于理解来说 1.UNICODE 从概念上讲,是与 ASCII 编码规则相对应的,都是为了用二进制的机器码来表示字符(也就是文字)而制定的规则. //UNICODE是这个种规则的名字,好比你叫张三,他叫李四

    2.”代码点”(code point)相当于”英文字符”的ASCII编码 //好比 ASC(“A”)函数会返回65,也就是机器码的0100 0001

    3.UCS-2,UCS-4是与UNICODE编码规则相关的”名词”,是表示”字符编码”(code point)使用几个字节进行编码 //废话,编码越长,能容纳的字符个数越多,好比手机号11位数比10位数容纳的用户个数大10倍一样

    4.UTF16,UTF32,UTF8,还有big endian,little endian等等,可理解为”字符编码”(code point)的在硬件存储设备上的实际存放次序 //这个不太好比喻,好比是用winrar进行压缩还是用winzip进行压缩,只是算法不同,最终都能被正确的算法解压还原.

  15. 文中提到: “UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。不难猜到,UTF-16是完全对应于UCS-2的,… ”

    From wiki: “UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节(2字节)储存,但UTF-16却无法相容于ASCII编码。

    UTF-16可看成是UCS-2的父集。在没有辅助平面字符Mapping of Unicode character planes(surrogate code points)前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支援UCS-2编码,那其实是暗指它不能支援在UTF-16中超过2bytes的字集。对于小于0×10000的UCS码,UTF-16编码就等于UCS码。”

  16. 非常受用,其它很多地方的资料就是迷惑别人的,而这篇文章耳目一新,一下看懂!

  17. 其取值范围为 U+0000~U+FFFF。

    意思是说范围为:

    0×0000-0xFFFF

    吗?

    U+是什么意思呢?

  18. 而且UTF-8不再需要BOM字节。 ⇒哈哈,楼主太绝对了吧! 前几天,我用java从数据库读出一个大的String,把这个String作为新建的csv文件的内容。String里面是中日英三种语言的。如果只是用UTF-8的话,Notepad++这种工具打开没问题,单用excel打开就乱码了。好像是因为excel默认的utf8文件是带bom的,所以我就在String前面加上了BOM,结果就全部工具打开全OK了~~~ ==》 用notepad保存的时候选择utf-8编码格式,用ultraedit查看,的确是没有bom的

    楼主其实是有BOM 的 当使用UTF-8编码的时候BOM对应的字节数组不是Unicode里的OxFF OxFE 了。而是 OxEF OxBB OxBF而用UE打开这个txt发现开头确实有这三个字节数组。

    请指教 huting0211@gmail.com

  19. UTF-8用1~4个字节来表示代码点。

    楼主这不是吧!应该是1~6个字节。

  20. Fondée en 1962, Yves Saint Laurent est synonyme d’élégance, d’innovation et de flair. En 1966, le prêt-à-porter Yves Soldes YSL Rive Gauche a été introduit, répondant à la demande de faire plus largement vêtements de luxe de marque de luxe Chaussures Yves Saint Laurent disposition.Le est l’abréviation de Bottes Yves Saint Laurent dont le nom complet est Escarpins Yves Saint Laurent Mathieu-Saint–Laurent et il est un célèbre couturier français qui a été considéré comme l’un des designers les plus influents du 20ème siècle. Stefano Pilati est le directeur créatif et force motrice derrière l’étiquette d’Yves Plates Yves Saint Laurent nous voyons aujourd’hui, ses créations restent fidèles aux racines de l’étiquette, offrant sophistiqués, Sacs Yves Saint Laurent des collections élégantes dans les meilleurs matériaux.

  21. Carefully listened to,spiderman beats headphone, you will find the two singles from the adapter to get rid of the feeling of insecurity was stuffed. Monster Cheap Beats by dr dre has been a good brand representatives, quality guaranteed absolute.Monster is a revolutionary headset high-performance monster.Diamond Beats By Dre sony ipod headphones rap instrumentals beats. Bloodshot eyeballs authored 50 songs afforded. They have the Cheap Beats By Dre Studio but they are fake tho. But you get them for less than half the price and from what I have heard they work nearly as well as the.453634675

  22. Enjoy clear sound with Beats By Dre now, Cheap Beats cheap beats By Dre of high quality deserve you to buy, high definition Dre Headphones with free shipping for you to.Monster Beats By Dre Headphones Hot Sale.Cheap Beats Cheap Beats By Dre Studio by dre headphones with Free Shipping.Beats Headphones for sale and free shipping. We provide high quality and best service. We make an effort ferrari beats by dre to create an atmosphere of trust and honesty,It works ! DGFS

发表评论

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

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>