上一篇《字符编码发展史4 — Unicode与UTF-8》我们讲解了Unicode字符集与UTF-8编码。本篇我们将继续讲解字符编码的第三个发展阶段中的UTF-16和UTF-32。
2.3. 第三个阶段 国际化
2.3.2. Unicode的编码方式
2.3.2.2. UTF-16
UTF-16也是一种变长编码,对于一个Unicode字符被编码成1至2个码元,每个码元为2个字节(16位)。UTF-16编码会有字节序的问题,所以根据大小端又分为大端UTF-16(UTF-16 BE)和小端UTF-16(UTF-16 LE)。
1. 基本平面(码点范围U+0000-U+FFFF)
在基本多语言平面内的码位UTF-16编码使用1个码元且其值与Unicode是相等的(不需要转换)。举例如下:
Unicode | 字符 | UTF-16(码元) | UTF-16 LE(字节) | UTF-16 BE(字节) |
---|---|---|---|---|
U+0041 | A | 0x0041 | 0x41 0x00 | 0x00 0x41 |
U+03A9 | Ω | 0x03A9 | 0xA9 0x03 | 0x03 0xA9 |
U+6653 | 晓 | 0x6653 | 0x53 0x66 | 0x66 0x53 |
2. 辅助平面(码点范围U+10000-U+10FFFF)
辅助平面的码点在UTF-16中被编码为一对双字节(16位)的码元(即32位,4字节),称作代理对(surrogate pair
),编号范围:0xD800~0xDFFF
,也就是前文提到的代理区的范围。这也就是为什么基本多语言平面会保留一块代理区(0xD800~0xDFFF
)的码点不定义任何字符的原因。
组成代理对的两个码元前一个称为前导代理(lead surrogates
)范围为0xD800-0xDBFF
,可表达1024(2^10)个码元;后一个称为后尾代理(trail surrogates
)范围为0xDC00-0xDFFF
,可表达1024(2^10)个码元。这样两个码元组合在一起就可以表达 2^20
(2^10 * 2 ^ 10
)个编码,正好和辅助平面的码点范围U+10000-U+10FFFF
对应。
UTF-16辅助平面代理对与Unicode的对应关系如下表。
- 第一列: 表示前导代理。
- 第一行: 表示后尾代理。
- 表格内容: 表示Unicode的码点编号。
\ | 0xDC00 | 0xDC01 | … | 0xDFFF |
---|---|---|---|---|
0xD800 | U+10000 | U+10001 | … | U+103FF |
0xD801 | U+10400 | U+10401 | … | U+107FF |
⋮ | ⋮ | ⋮ | ⋱ | ⋮ |
0xDBFF | U+10FC00 | U+10FC01 | … | U+10FFFF |
举例如下
Unicode | 字符 | UTF-16(码元) | UTF-16 LE(字节) | UTF-16 BE(字节) |
---|---|---|---|---|
U+2A6A5 | 𪚥 | 0xD869 0xDEA5 | 0x69 0xD8 0xA5 0xDE | 0xD8 0x69 0xDE 0xA5 |
3. 优缺点
- 优点:
- 绝大部分的文字都可以用两个字节编码,对于CJK文字是比较节省空间的;
- 文本处理比UTF-8方便得多。
- 缺点:
- 存储和传输需要考虑字节序的问题;
- 不兼容ASCII(准确的说是半兼容,编码值是一样的,只是需要用两个字节来表示)。
2.3.2.3. UTF-32
1. UTF-32的编码规则
UTF-32是一种定长编码,使用1个32bit的码元,其值与Unicode编码值相等。举例如下:
Unicode | 字符 | UTF-32(码元) | UTF-32 LE(字节) | UTF-32 BE(字节) |
---|---|---|---|---|
U+0041 | A | 0x00000041 | 0x41 0x00 0x00 0x00 | 0x00 0x00 0x00 0x41 |
U+03A9 | Ω | 0x000003A9 | 0xA9 0x03 0x00 0x00 | 0x00 0x00 0x03 0xA9 |
U+6653 | 晓 | 0x00006653 | 0x53 0x66 0x00 0x00 | 0x00 0x00 0x66 0x53 |
U+2A6A5 | 𪚥 | 0x0002A6A5 | 0xA5 0xA6 0x02 0x00 | 0x00 0x02 0xA6 0xA5 |
UTF-32同样有大小端的问题。
2. 优缺点
- 优点:是编码定长容易进行文本处理。
- 缺点:是浪费存储空间及存在字节序的问题。
2.3.2.4. UCS-2 与 UCS-4
前文提到:历史上存在两个独立的尝试创立单一字符集的组织,即 国际标准化组织(ISO
)和统一码联盟。统一码联盟除了收录字符集外,还制定过两套字符编码方案:UCS2和UCS4。
1. UCS-2
UCS-2是一种定长编码,编码范围为0x0000-0xFFFF,在基本多语言平面内与UTF-16是等价。UCS2没有类似于UTF-16中代理对的概念,所以对于0xD869 0xDEA5会识别成两个字符。所以它只能表示基本平面的字符,不能表示全部的Unicode字符。UCS2后来被UTF-16替代,现在基本已经被废弃了。
2. UCS-4
UCS-4的编码方式与UTF-32几乎一样,后来两个组织统一标准后,就变成了UTF-32。不过ISO组织规定Unicode的编码空间会限定在0x000000~0x10FFFF
之间,而UCS4的编码范围能到0~0xFFFFFFFF
。因此也可以认为:UTF-32 是 UCS-4 的一个子集。
未完待续…… 欲知后事如何,且看下回分解。
下回预告:字符编码发展史6 — BOM字节序标记。
历史文章推荐:
字符编码发展史4 — Unicode与UTF-8
字符编码发展史3 — GB2312/Big5/GBK/GB18030
字符编码发展史2 — ISO-8859-N
字符编码发展史1 — ASCII和EASCII
大家好,我是陌尘。
IT从业10年+, 北漂过也深漂过,目前暂定居于杭州,未来不知还会飘向何方。
搞了8年C++,也干过2年前端;用Python写过书,也玩过一点PHP,未来还会折腾更多东西,不死不休。
感谢大家的关注,期待与你一起成长。