首先介绍unicode,最开始计划有31位,但到后来一执行,发现0x 0~10FFFF就够用了,仅有21位。
UTF-8是一种变长、多字节编码方案,从一字节模式,到六字节模式。虽然unicode只到21位,但是查看pcre2的源代码发现,对UTF-8的支持到六字节。
0*******
110***** 10******
1110**** 10****** 10******
11110*** 10****** 10****** 10******
这里仅罗列到四字节模式。
分析一个UTF-8编码的文件,看第一个字节是否是0开头的,如果是,就是一字节模式,该模式兼容基本ASCII码,也是128个码位。
如果第一字节以110开头,则使用双字节模式,接下来的那个字节以10开头。
如果是1110开头则是三字节模式,如果是11110开头则是四字节模式。
UTF-16有双字节模式、四字节模式两种。
******** ********
110110** ******** 110111** ********
有人会发现,双字节模式下,遍历了16比特的全部65536种情况,那该怎样区分双字节模式和四字节模式呢?
原来,设计unicode时早有安排,编码110110-- --------对应的1024个码位留空。因为有10个星号,所以是1024个码位。同理,编码110111-- --------对应的1024个码位也为空。共有2048个码位留空,专门为了UTF-16能正常工作。
即使这样,四字节模式的UTF-16也只有20个星号啊,可unicode最多有21位,还差1位呢?
算法是这样的:
设待编码为U,当0≤U≤FFFF时,采用双字节模式,此时的U不超过16位,双字节正好放得下。
若10000≤U≤10FFFF,则需计算U’=U-0x10000,U’的取值范围是:0≤U’≤FFFFF,U’不大于20位,可以放在四字节模式的模板内。
关于UTF-8和UTF-16的讨论,和汉字的长度有关。在UTF-8中,一个汉字占用3字节。这里说的是基本汉字那2万多个,对于不常用的汉字,需占用4字节。在UTF-16中,一个基本汉字占用2字节。
许多程序员,尤其是老程序员,他们年轻时,unicode还未普及,那时人们记住了:一个汉字两个字节。所以,他们更容易选择UTF-16。还有人坚定地选择GBK,这是一种中国的国标编码。
然后,互联网普及了。人们发现各国的编码不通用,所以就有了unicode。
至于UTF-8中一个汉字占3字节,这没什么的。表达同样的意思,用英语和用汉语,英语的字母个数,约是汉字个数的3倍。如integer,7字节;整数,6字节。二者相差不大。
另外,UTF-16有大端小端问题。且UTF-16已经满了,不能扩充,它甚至需要计算U’来压缩至20位。而UTF-8没有大端小端问题,且可以扩充至31位。
所以,我更喜欢UTF-8,至于GB2312、GBK等编码,早已不再使用了。