Unicode编码详解

经常碰到乱码,为了弥补这一块的知识,在网上查阅了大量的资料,发现关于字符编码有很多概念,很多文章也是从不同角度来讲解,也能碰到相矛盾的文章,被绕了很久,最终才整理出我自己的理解,不一定完全准确,但是至少是自己经过思考和总结出来的,所以看文章只能是辅助自己思考的过程,要始终怀着怀疑和批判态度去思考。


什么是Unicode?

Unicode的学名是"Universal Multiple-Octet Coded Character Set",从名称来看Unicode属于一种字符集,字符集就是一张表,里面收录了大量的符号和文字,每个符号和文字有与之对应的标识。所谓的标识 ,就是对对这个字符集合里的所有字符进行编码,Unicode的编码空间是从U+0000到U+10FFFF(16进制),整个编码空间又被划分为17平面,每个平面包含(65535)个码位,而第一个平面就已经包含了大多数国家常用的字符,所以第一个平面又称为“基本多语言平面”,其它平面称为辅助平面。除了Unicode,我们也会碰到UCS,UCS与Unicode虽然产生于不同的两个组织,但是因为编码要统一,所以它们现在的内容基本保持一致,可以简单的认为,它们就是一个东西,而UCS-2和USC-4是从USC这个观念下划分出来的,可以简单的理解为USC-2对应Unicode中“基本多语言平面”的范围,UCS-4只是在UCS-2前面加了0x0000,前面不变。USC-2用两个字节对语言符号进行编码,USC-4用4个字节对语言符号进行编码。


UTF
UTF的全称是UCS Transformation Format,从名称来看,UTF是用于数据存储或传递的一种规范。跟Unicode不同,Unicode是一个
字符集合,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储


UTF-16
UTF-16是Unicode字符编码的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数的序列,用于数据存储或传递。在Unicode字符集U+0000-U+ffff的范围中,也就是在第一个平面中,utf-16一律采用2个字节来存储,在辅助平面中,utf-16采用两个双字节,也就是4个字节来存储,所以整体来看utf-16是一种变长编码。在Unicode字符集中从U+D800到U+DFFF之间的码位区段永远都不会被映射字符,因为utf-16会利用这个区段的码位来对辅助平面的字符码位进行存储(也就是把这个区段的值转换成一串二进制数与辅助平面的符号相对应)。如果说utf-16利用这个区段的码位来对辅助平面来存储,在识别到两个字符的时候,系统会去查Unicode字符表,发现找不到对应的字
符(因为没有映射字符),所以系统就会认为采用的存储方式是两个双字节作为一个字符,然后再继续往前读取一个字节,最后系统会拿着这个数值去找Unicode字符集中辅助平面的字符。但是反过来讲,如果这个区段被占用了,这个区段的码位有相对应的字符的话,utf-16还利用它对辅助平面来存储的话,当读取到2个字节的时候,系统
去查字符表,然后突然查到有对应的字符,那么它就会认为应该是2个字节作为一个字符,然后它会按照“基本多语言平面”的编码方式来解码,所以utf-16对辅助平面的存储也就无效了。
相对于UTF-8,UTF-16好处在于大部分字符都以固定长度的字节 (2字节) 储存,但是它不兼容ASCII码。


UTF-32
      UTF-32一律采用4字节存储,空间浪费比较大,用的也很少,不多提。


UTF-8

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。UTF-8的编码规则很简单,只有二条:

对於单字节的符号,字节的第一位设为0,后面7位为这个符号的Unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的,所以UTF-8兼容ASCII码。

对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的Unicode码。




已知“严”的Unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。通过这个例子,可以看到“严”的Unicode码是4E25,UTF-8编码是E4B8A5,两者是不一样的。一个代表着在字符集中
的编号,另一个代表在计算机的存储和传递方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章