# UTF-8
UTF-8是一种字符长度可变的Unicode编码方式。他可以编码Unicode中的所有码位,共
17∗216−2048(BMP.Surrogate)=1112064个 17 ∗ 2 16 − 2048 ( B M P . S u r r o g a t e ) = 1112064 个
UTF-8的规则很简单:
- 存储长度:从最低
1
字节到最高4
字节可变。但是被RFC3629
规范之后,只能使用Unicode(U+0000 ~ U+10FFFF
)定义的区域,现在UTF8的最高为4
字节,但理论上可以支持到最高6
字节的编码范围 - 单字节规则:最高位永远为
0
,完全和ASCII编码相同 - 多字节规则:的第一字节的高位决定了序列的长度,其他字节的高位固定为
10
开头
我们来看一下Unicode的编码规则:
优点
- 对于ASCII编码的文件完全兼容,且只用单字节就可以存储。对于部分只用到ASCII字符来说,存储非常节省。
- 保证一个字符的序列出错不会影响另一个字符的序列。非常适合网络传输
- 因为以字节为编码单元,无需考虑字节顺序的问题。所以也不需要
BOM
缺点
- CJK文字分布在
U+2E80
以上,属于三字节的范畴。比起GB2313
的双字节要多一半的存储空间 - 因为是可变长度编码,无法实现O(1) O ( 1 ) 的搜索和随机访问。
# UTF-16
UTF-16的长度为双字节或四字节的可变长度。双字节为Unicode的BMP平面,四字节通过High Surrogate
和Low Surrogate
组合。可以组合出Unicode的16个补充平面。字符覆盖Unicode所有码位,数量为
65535+1024∗1024−2048=216∗17−2048(BMP.Surrogate)=1112064 65535 + 1024 ∗ 1024 − 2048 = 2 16 ∗ 17 − 2048 ( B M P . S u r r o g a t e ) = 1112064
转换规则:
BMP平面中的码位
即小于
U+10000
,数值直接等于码位的数值,并使用双字节
BMP平面下的转换过程
如
$
U+0024
对应的二进制是
0000 0000 0010 0100
UTF16编码之后,和二进制完全相同。不需要做任何转换
最终得到的UTF16编码位
0024
辅助平面的码位
即大于等于
U+10000
,使用代理对的模式进行编码
前16位使用
U+D800 ~ U+DBFF
,后16位使用
0xDC00 ~ 0xDFFF
辅助平面算法过程
如
U+2BB62
对应的二进制是
0010 1011 1011 0110 0010
0x2BB62
减去
0x10000
得到
0x1BB62
=
0001 0100 1011 0110 0010
前10位为
00 0101 0010
=
0x0082
加上
0xD800
得到
0xD882
为高代理
后10位为
11 0110 0010
=
0x0362
加上
0xDC00
得到
0xDF62
为低代理
得到UTF16编码为
D882 DF62
优点
- 原本Unicode只有BMP平面的时候,UTF-16为固定长度存储。计算长度和索引非常方便。但是后来扩展Unicode之后,强行加入代理对才能解决问题。导致这个优势不复存在。
- 和UTF-8一样,因为双字符是成对的,高代理低代理或者低代理高代理。每个16位均有范围,所以另一个字符的一部分是这个字符的一部分的可能性是0。部分出错可以立刻得知。一个字符出错不会影响后续字符。
缺点
- 不兼容ASCII
- 由于硬件和系统不同的关系,需要定义字节序
- 最少需要使用2字节,最多需要4字节。相比UTF-8的存储大了很多。
# UTF-32
定长存储。每个字符都使用32位4字节进行存储。简单暴力。
优点
- 定长存储,计算长度和索引超级快速。然而Unicode新标准的emoji中有
ZWJ
的存在。这个优势也会在以后逐渐消失了。
缺点
- 存储空间太大。
# UCS-2
UCS-2
是UTF-16
的子集。他用16位对BMP平面的所有码位进行编码。缺点是因为定长多一个0x0
,所以不兼容ASCII。
# UCS-4
UCS-4
编码方式和UTF-32
相同。原本UTF-32
是USC-4
的子集,但后来的各种修改后,现在USC-4
和UTF-32
相当于相同的编码方式。