天天看点

字符编码学习之二,UTF-16,USCII,GB2312编码

上一篇讲完了utf8编码,这篇接着讲UTF-16,UTF-16和UTF-8一样也是变长编码,不同的是,UTF-16是2字节或4字节。基本平面(BMP)的2^16个字符的Unicode编码直接作为UTF-16编码,所以单字节的ASCII在Unicode中也是两字节编码。其他16个辅助平面的字符使用4字节编码。问题来了,如何区分一串6字节的UTF-16编码是一个两字节的字符加一个四字节的字符,还是3个2字节的字符了?

UTF-16有一个很巧妙的设计规则,在基本平面内,从U+D800到U+DFFF是一个空段,即这些码点不对应任何字符。因此,这个空段可以用来映射辅助平面的字符。具体来说,辅助平面的字符位共有2^20个,也就是说,对应这些字符至少需要20个二进制位。UTF-16将这20位拆成两半,前10位映射在U+D800到U+DBFF(空间大小2^10),称为高位(H),后10位映射在U+DC00到U+DFFF(空间大小2^10),称为低位(L)。这意味着,一个辅助平面的字符,被拆成两个基本平面的字符表示。

所以,当我们遇到两个字节,发现它的码点在U+D800到U+DBFF之间,就可以断定,紧跟在后面的两个字节的码点,应该在U+DC00到U+DFFF之间,这四个字节必须放在一起解读。

如果是辅助平面字符,Unicode 3.0版给出了转码公式。

如果一个Uncode码为c的字符是辅助平面字符那么它的UTF-16转化公式为

H = floor((c-0x10000) / 0x400)+0xD800

L = (c - 0x10000) % 0x400 + 0xDC00

比如下图的八分音符, Unicode码为U+1D160,它的UTF-16码为:

高位 floor((0x1D160-0x10000) / 0x400)+0xD800 = 0xD834

低位 (0x1D160 - 0x10000) % 0x400 + 0xDC00 = 0xDD60

0xD834 DD60长度为4字节。我们可以在里任选一个辅助平面的字符经行校验计算

字符编码学习之二,UTF-16,USCII,GB2312编码

我们在某些编辑器里面还可见到USC-II编码,这其实可以看成是UTF-16的一个子集,即用两个字节的Unicode码编码的主平面(BMP)的65536个字符。而辅助平面的字符无法用USC-II编码表示。

继续阅读