带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(4) https://developer.aliyun.com/article/1240884?groupCode=tech_library
10.4.1代理对
UTF-16跟UTF-8、GB系列等都算是变长字节,但是设计初衷却不一样,像GBK是为了兼容ASCII,但是UTF-16一开始就没考虑要兼容ASCII,所以他的变长是为了节约存储空间而采用的自然增长方案,当空间不够的时候增长到4个字节。
那问题来了,我怎么知道存储的4个字节是表示一个字符,还是两个字符呢?比如当程序遇到字节序列01001110 00101101 01010110 11111101时,到底是判断成一个字符还是两个字符?
这就需要一个前导识别,比如GB2312识别第一个字节高位是不是1来判断是单字节还是双字节,但是UTF-16的高位1已经被用来编码了,当然这也难不倒我们,第一位被用了那么就用前几位的组合形式。
UTF-16采用了代理对来解决,也就是高半区编码(前两个字节)范围D800-DBFF(称为代理码点),低半区编码(后两个字节)范围DC00-DFFF,组成一个四个字节表示的字符。
上述前导6位组合也是有讲究的,ISO组织要求编号范围是0~10FFFF,也就是说用20位就可以表示10FFFF个字符,对于双码元就是每个码元各自负责10位,一个码元是16位,数字位占去10位后,剩下的6位做为前导位。
当UTF-16使用一个码元表示的时候,Unicode字符编号跟码元序列是等值映射的,但是当采用双码元后,字符编号跟码元序列就需要转换了。
下面是码元和Unicode编号值之间的计算公式。
换算码元序列(CH高半区/CL低半区):
换算字符编号(CH高半区/CL低半区):
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(6) https://developer.aliyun.com/article/1240882?groupCode=tech_library