Unicode 笔记

Unicode前端emoji

发布于 2020

1. Unicode 是什么?

有一个想法,将全世界所有的字符号都包含在一个集合里边,任何机器支持这一个集合就行了,再也不会有乱码了。基于这个想法,Unicode 码应运而生。它用数字编号来表示符号,到 7.0 版,已经有了 109449 个符号。一般用 26 进制表示,'U+4E49'表示字符'义','U+'是前缀,整体叫做码点

集合分为几个区间,U+0000U+FFFF 是最常用的字符,称为基本平面,剩下的 U+010000U+10FFFF 称为辅助平面

2. 编码方式

平常说的 UTF-8,UTF-16 就是说的码点的编码方式。UTF-32 指无论是什么码点,一律使用 4 个字节表示,一共是 8 位 16 进制数,位数不足的,在前边补 0,例如 U+389D = 0x0000 389D。UTF-8 字节数灵活,用 1 个字节能表示的用 1 个字节,用两个字节才能表示的,用两个字节,还可能是 3 个 4 个字节。同样的文本 UTF-8 占的存储空间比 UTF32 小多了。所以,网页编码大部分使用的是 UTF-8。

3. UTF-16

重点说一下 UTF-16。UTF-16 介于以上两者之间,规则也很简单,基本平面的字符占用 2 个字节,辅助平面的字节占用 4 个字节。因为常用的字符都在基本平面,所以 UTF-16 比 UTF-32 所占空间要小。当我们看到 4 个字节,如果前两个字节码点的范围是 U+D800 到 U+DBFF,那么后两个字节码点一般在 U+DC00 到 U+DFFF 范围内,那么它就是一个 4 字节字符。但是 U+D800 到 U+DBFF 范围内的 2 个字节的字符怎么办?在基本平面里边 U+D800~U+DBFF 是一个空段,不对应任何字符(不知道是不是有意为之),所以用这段来表示 4 字节字符的前段,也叫高位,后边的 U+DC00 到 U+DFFF 叫低位。

所以,当我们遇到两个字节,发现它的码点在 U+D800 到 U+DBFF 之间,就可以断定,紧跟在后面的两个字节的码点,应该在 U+DC00 到 U+DFFF 之间,这四个字节必须放在一起解读。

给一个辅助平面的码点,怎么转化成 UTF-164 字节形式呢?有一个公式可用:

H = Math.floor((c - 0x10000) / 0x400) + 0xd800;
L = ((c - 0x10000) % 0x400) + 0xdc00;

4. javascript 中的 Unicode

javascript 采用 Unicode 字符集,支持的编码方式是 UCS-2。UTF-16 是 UCS-2 的超集,至于 UCS-2 是什么,请自行百度。在 javascript 中处理字符串时,可以看做是 UTF-16 编码。遇到 4 个字节的字符,String.prototype.length 会得到 2,不过在 es6 中增加了新的 api 处理 4 个字节字符的方法,这里就不展开介绍了。js 中的表示方法是'\u'+四位 16 进制数,例如'\u4f60'表示中文'你',这是一个长度是 1 的字符。'\u004F\u030C'表示符号'Ǒ',lendth 长度是 2。匹配辅助平面的字符的正则:/[\uD800-\uDBFF][\udc00-\udfff]/,匹配到的字符 length 都是 2。首先要将码点转化为高位和低位形式,再与正则比较判断。

5. javascript 中处理 emoji

emoji 实质上也是 Unicode 码,也可以在 javascript 中处理。大部分 emoji 是 4 个字节,由高位+低位两端编码组成,只要解析的时候不把高位和低位分开,就不会出现'乱码'的情况。但是有些 emoji 是由多个 emoji 连接而成,例如:

U+1F468:男人
U+1F469:女人
U+1F467:女孩

使用连接符号 U+200D 连接,U+1F468 U+200D U+1F469 U+200D U+1F467,就会显示一个新的 emoji 表情:家庭,但是如果系统不支持这种表示,还是会显示 3 个单独的表情。