Unicode 详解
字符集&编码
- charset 是 character set 的简写,即字符集。
- encoding 是 charset encoding 的简写,即字符集编码,简称编码。
Unicode (UTF-8 UTF-16 UTF-32) 歧义
由于各种原因,必须承认,在不同的语境下,“Unicode”这个词有着不同的含义,它可能指:
- Unicode 标准
- Unicode 字符集
- Unicode 的抽象编码(编号),也即码点(code point)。
- Unicode 的一个具体编码实现,通常即为变长的 UTF-16(16 或 32 位),又或者是更早期的定长 16 位的 UCS-2。
编号 编码
- 字符 <–> 编号 <–> 编码
- 编号与编码的主要区别在于编号不涉及具体使用多少字节来表示、是用定长还是变长方案等细节问题。编号仅仅是一个抽象的概念,是把字符数字化的一个过程。
- 字符集 是一组映射关系[字符 - 编号] 具体字符被映射成一个唯一的code--码点 例如:
- U+[XX]XXXX 是码点的表示形式,X 代表一个十六制数字,可以有 4-6 位,不足 4 位前补 0 补足 4 位,超过则按是几位就是几位。具体范围是 U+0000~U+10FFFF
- U+0048,U+00E6,U+4F60,U+1D11E(这是个五位的码点)
- 受编码影响 编号通常也以十六进制形式书写,并保持固定的位数,不够就在前面填充 0,比如把 48 写成 0048;又比如: U+1D11E 就是一个一个五位的编号。
- 方便扩展,编码常跳过某些码位,甚至保留大片的区域未定义或作保留用途。
小结
- code point - 码点 - 对字符的数字化抽象 - 不体现具体的编码转换格式
- 编码 - UTF(Unicode Transformation Format) - Unicode转换格式 - 将抽象的数字转化成具体的编码 - 编码对应[存储字节数、是否变长...]
- Unicode 的核心就是为每个字符提供唯一一个数字编号。code point 例子: 'a' - 97 - 0061 - U+0061(码点 - 16进制)
具体编码格式
三种编码方案的定变长与字节数总结:
- UTF-8:变长,1-4 字节;
- UTF-16:变长,2 或 4 字节;
- UTF-32:定长,4 字节。
定长与变长
- 在容量 和 效率之间全行,出现了变长的编码方案。
- 默认标示位,变长方案。损失了很多有效码位
- 出现了代理区 做 区分的 方案
Unicode
-
Unicode 是 Unicode Standard(Unicode标准)的简写,所以 Unicode 即是指 Unicode 标准。
-
它脱离具体平台、语言,给每一个字符 一个唯一的数字code--码点(code point)
-
码点的格式
U+[XX]XXXX X:代表一个十六制数字
可以有 4-6 位,不足 4 位前补 0 补足 4 位,超过则按是几位就是几位。以下是码点的一些具体示例:U+0048,U+4F60,U+1D11E。最后一个是5位的码点。 -
范围[U+0000,U+10FFFF] 理论大小为 10FFFF+1=110000(16进制)[FFFF+1 转10进制 = 65536 ]。是一个百万级别的数。
-
平面[Plane]为了更好分类管理如此庞大的码点数,把每 65536 个码点作为一个平面,总共 (1 x 16 + 1 )= 17 个平面。
- first Plane = BMP(Basic Multilingual Plane 基本多语言平面),也叫 Plane 0,它的码点范围是 U+0000 ~ U+FFFF
- 后续的 16 个平面称为 SP(Supplementary Planes)。范围超过了 U+FFFF即超过了 4个byte了。
- CJK 统一汉字(CJK:Chinese, Japanese, and Korean,中日韩)在first plane 中间很大一片区域
- 还有一片空白区域--代理区 这段空白从 D8~DF。其中前面的红色部分 D800–DBFF 属于高代理区(High Surrogate Area),后面的蓝色部分 DC00–DFFF 属于低代理区(Low Surrogate Area),各自的大小均为 4×256=1024。
-
UTF 即是 Unicode 转换格式(Unicode (or UCS) Transformation Format)
- UTF-32
- 码点最大的 10FFFF 占 21 位,UTF-32 采用的定长4 byte 则是 32 位。高位补 0 的形式补够 32 位即可,缺点占用空间太大。
- 4字节 XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
- UTF-8
-
变长的编码方案:1,2,3,4 四种 byte 组合
-
采用高位保留方式 来区别不同变长
- 1字节 0XXX XXXX
- 2字节 110X XXXX 10XX XXXX
- 3字节 1110 XXXX 10XX XXXX 10XX XXXX
- 4字节 1111 0XXX 10XX XXXX 10XX XXXX 10XX XXXX
-
码点对应字节
- 转二进制,去掉高位0 判断采用几字节
- 一字节 有效位7位兼容ASCII [码点] U+0000 ~ U+007F (0~127)
- 二字节 11位有效,2^11=2048 个编码空间 码点 U+0080 ~ U+07FF (128~2047)
- 这里码点从 128~2047,因为去掉了一字节的码点,所以不会占满 2048 个编码空间,是有冗余的,但你不能把适用于一字节的码点放到这里来编码。下同。
- 三字节 16位有效,65536 个编码空间 码点U+0800~U+FFFF (2048~65535)
- 存着绝大部分汉字
- 四字节 21位有效,前面说到最大的码点 10FFFF 也是 21 位,U+FFFF 以上的增补平面的字符都在这里来表示。
-
码点转换
- 将码点转换成 2进制
- 将二进制数 按照UTF-8 固定位分组
- 选中几字节模式后,高位不足 补0
- 重新将 2进制数 转换成16进制数
-
N 字节模式,首字节以“N 个 1 再加 0 ”打头,后跟“N-1”个以“10”打头的字节。
-
- UTF-16
- 变长的 2 或 4 字节编码模式
- BMP内的字符使用 2 字节编码
- 其它的则使用 4 字节组成所谓的代理对来编码
- 代理区
- 鸟瞰图中,一片空白的区域,就是代理区(Surrogate Area),
- 为了编码增补平面中的字符而保留的,总共有 2048 个位置,均分为高代理区(D800–DBFF)和低代理区(DC00–DFFF)两部分,各1024,这两个区组成一个 二维的表格,共有:
1024 × 1024 = 2^10×2^10 = 2^4×2^16 = 16×65536
- 它恰好可以表示增补的 16 个平面中的所有字符
- 码点转换
- BMP 中直接对应,无须做任何转换
- 增补平面 SP 中:
- 减去10000(16进制)[第一个平面中的所有码点]
- 除以代理区的行宽[ 1024(10进制) ] 商:第几个高代理区 余数:第几个低代理区
-
Lead = (码点 – 10000(16)) ÷ 40016 + D800 Trail = (码点 – 10000(16) % 40016 + DC00
- 转换请用API 通过位移运算更高效
- 变长的 2 或 4 字节编码模式
- UTF-32