事情的起因是要写一个 Android 例子,用 RecyclerView 花样展示各个国家名字。例子写完后想在国家名字后面加上该国国旗,于是牵涉出 Emoji 和字符编码,顺便总结分享一下。
Unicode 简史
- 字符 是地球文明相关的各个符号。
- 1 个电子管 亮 / 灭,2 种状态(二进制)。
- 8 个晶体管 亮 / 灭,256 种状态(2 的 8 次方),这个 8 位物理存贮单元存贮单元称为 字节。
- 1 个 字节 里的前 128 位,包含控制码、空格、标点符号、数字和大小写英文字母,这个方案叫做 ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)。
- 1 个 字节 里的后 128 位,引入更多的字母和符号,称为 扩展字符集(Extended ASCII Codes)。
- 世界各地捣鼓出许多区域性字符编码标准,如 GB2312、GBK 和 Big5 等。
- ISO(国际标谁化组织) 立志解决字符编码巴别塔问题,搞了一个包括所有字符的 字符集,英文名 Universal Multiple-Octet Coded Character Set,简称 UCS,俗称 Unicode。
Unicode 特点
- Unicode 是 ISO 推行的一种 字符集
- Unicode 用 2 个 字节 ,即 16 位来表示所有 字符,编码范围从
U+0000到U+10FFFF。 - Unicode 为每个 字符 分配唯一的 码点(Code Point)
UTF-8 和 Unicode 的关系
- UTF-8 是当前互联网最流行的 Character Encoding
- UTF 全称是 UCS Transfer Format,UTF-8 顾名思义每次传输 8 位数据。
- UTF-8 是一种 Unicode 的 传输格式,即是一种 编码规则,可以将 码点 转换为字节序列的规则。
- UTF-8 会将一个 字符 编码为 1 到 4 个字节。单字节的字符,字节的 第 1 位 设为 0。英语文本只占 1 个字节,和 ASCII 里的情况相同。n(n>1) 个字节的字符,第 1 个字节 的 前 n 位 设为 1,第 n+1 位 设为 0,后面字节 的 **前 2 位 **都设为 10,这 n(n>1) 个字节的其余空位填充该字符 Unicode 码,高位用 0 补足。
U+ 0000 ~ U+ 007F: 0XXXXXXX U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX U+10000 ~ U+1FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
Emoji 和 Unicode 的关系
- Emoji,絵文字,えもじ 是 字符,因此 Emoji 是 Unicode 这个 字符集 里的一部分。
- 一个 Emoji 至少由一个 码点 表示。
- 当某个 Emoji 由多个 码点 表示时,我们称之为 序列(Sequences)。
- 可在 Full Emoji List, v5.0 页面查看所有 Emoji 的 码点 信息。
- 各个平台对 Emoji 的实现各不相同,比如 😂 Face With Tears of Joy 。
至此,想必大家已经对 Unicode、UTF-8 和 Emoji 的概念已经清楚了,接下来我们理论结合实际,通过手动编码搞明白 Emoji 是怎样通过 UTF-8 来表达的。
😂 face with tears of joy
😂 在 Unicode 里的 码点 是 U+1F602,按照 UTF-8 的规则对 U+1F602 进行编码。
1 F 6 0 2
0001 1111 0110 0000 0010 二进制的 1F602
-----------------------------------
000 011111 011000 000010 二进制的 1F602 根据 UTF-8 规则移位
11110XXX 10XXXXXX 10XXXXXX 10XXXXXX UTF-8 规则模版
11110000 10011111 10011000 10000010 代入模版后的二进制数
F 0 9 F 9 8 8 2 代入模版后的十六进制数
由上可知 😂 用 UTF-8 传输时需要 4 个字节:F0 9F 98 82。
🇨🇳 flag of China
🇨🇳 在 Unicode 里的 码点 是 U+1F1E8 U+1F1F3,属于 序列 这种情况,依照 UTF-8 规则变换,过程跟之前类似,这里不详写了,最后得到十六进制数是 F0 9F 87 A8 F0 9F 87 B3,传输时需要 8 个字节。