Unicode - 平面(Plane)的概念
2020-11-29
0. 前言
上篇介绍了 Unicode 的理论基础 —— 5 层字符编码模型,这篇文章我们来聊另一个困扰了我很长时间的概念——平面(Plane) 。
PS:Plane 在 Unicode 的语境下,指的是平面,而不是飞机。
1. 平面是什么?
先来复习一下 Code Space(码空间)这个概念,码空间就是指我们有多少个码位可以使用。
比如 7-bit ASCII 的码空间就是 2^7 = 128。
而 Unicode 刚问世的时候,是采取 16-bit 编码的,也就是 2^16 个码位。
但是 Unicode 里面的抽象字符 ACR 太多了,2^16 不够用啊~ 怎么办呢?
于是 Unicode 引入了平面的概念,用一个额外的 Byte 来标识平面号。
复习:不同的进制
-
十六进制:Hexadecimal,简称 hex,0-9 + A-F,逢 16 进 1;
-
十进制:Decimal,0-9,逢 10 进 1;
-
二进制:Binary,0,1,逢 2 进 1;
2 个 16 进制 = 8 个 2 进制。
1 Byte = 8 bit = 2 hex
2 Byte = 16 bit = 4 hex
Unicode 的表示方式
Unicode 的表示方式是:U+6 个十六进制的数字(U+hhhhhh)。
为什么是 6 个 16 进制的数字呢?因为我们刚才说了,前两位用来表示平面,后 4 位是码位。
所以,Unicode 能表示的符号 = 平面数*2^16 = 平面数*16^4 = 平面数*65,536。
换言之,每个平面有 2 Byte 的码位。
那么我们可以有多少个平面呢?
既然有一个单独的 Byte 来表示平面号,理论上我们可以最多有 256 个不同的平面。
不过 Unicode 的选择是分成 17 个平面,使用方式如下:
Plane 0(零号平面)的码位是从 0000 - FFFF(16 进制的 4 个 0 等于 2 进制的 16 个 0,代表 16 bit)。
Plane 0 包含了最常用的字符,也被称为 Basic Multilingual Plane(基本多文种平面,简称 BMP),共支持六万多个字符。
其他的 Plane 1 - Plane 16 被称为辅助平面。
大家可以看到,Plane 4 - Plane 13 目前还是完全没有被使用到的,所以 unicode 的码位足够我们使用啦~
Plane 15 和 16 是可以进行自定义编码的哦~ 有些项目需求可能会用到 Unicode 的这个特性。
小知识 1:奇妙的 Plane 0
因为 Plane 0 只需要用到 2 Byte,所以假如一个字符能对应到 Plane 0 的码位,系统就只需要传 2 Byte。
可惜 Plane 0 最多只能对应 6 万多个字符,那是不是意味着其他的字符必须要用超过 2 Byte 的码位来进行编码了呢?
我们之前将 Unicode 模型的时候也提到了,Unicode 并不是把字符和码位进行直接的映射。而在 Plane 0 里,码位区段 D800(55296)到 DFFF(57343)是永久保留码位。这样的“留白”就给了不同的编码标准一些自主性,比如 UTF-16 编码巧妙的利用了这保留下来的码位来对辅助平面内的字符进行编码。
另外 E000 - F8FF 是私人使用区间,也是可以自主编码的哦~
小知识 2 :Unicode Roadmap 的阅读方式
在 Unicode 的官网看到了 BMP 的编码图,长下面这个样子:
很显然,纵向是两个 hex 数字,那么横向为什么只有一个数字呢?BMP 应该有 2 Byte,也就是 4 hex 呀。
后来我才发现,这个表格简化了横向的数字,比如点击 Basic Latin 之后,我们可以看到,实际的范围是 0000 - 007F。
同理,表格里面的 008 - 00F 其实是 0080 - 00FF。
是不是奇怪的知识又增加了 😀。
PS: https://www.compart.com/en/unicode/plane 这个网站对每个平面的使用都有详细的解释,UI 也很好看~推荐!
2. 未解之谜
为啥分 17 个平面?
这个问题一直在我脑海中挥之不去,查了资料发现,大家的解释是:
-
hh 范围(16 进制):00-10;
-
hh 范围(10 进制):0-16,共 17 个数字,所以是 17 个平面;
There are 17 planes, identified by the numbers 0 to 16, which corresponds with the possible values 00–10 of the first two positions in six position hexadecimal format (U+hhhhhh).
但是,既然有两个 16 进制数字,为啥不直接从 00-FF 编号?或者从 00-11?这样不是能更加充分地利用起来吗(最多可以有 16^2 = 256 个平面)?
假如只需要 16 个 Plane,不需要那么多,那我们也可以只用一个 16 进制的数字来表示平面号(0-F),干嘛非要用两个?
我唯一能接受的解释是:
- 1 Byte = 8-bit = 2 Hex,所以传输的时候最小单位是 2 Hex,我们需要用 2 个 Hex 数字来对平面编号;
- 然后,一开始 Unicode 是用 16-bit 来设计的,设计师拍脑袋认为 17 个平面够用了;
- 现在 Plane 4 - Plane 13 都没有被用到,所以理论上来说,我们并不需要 17 个平面,但是当初就是这么设计的,大家都接受了;
也许是我想太多了= =
3. 结语
这篇文章讲了一个比较冷门的 Unicode 概念 - Plane (平面),平面的存在使得我们可以跳出 2 Byte(2^16)的编码上限。
-
Unicode 用一个单独的 Byte 来表示平面号,即 U+hhhhhh 里面的前两位 hh。
-
Plane 0 又称 BMP,BMP 里面有一些留白区间,赋予了不同编码标准一些自主性。
-
虽然无法理解为什么有 17 个平面,但暂时只能接受这个设定了~