Infinite Games

Less is More.

Unicode、UTF8、Emoji

Unicode

ASCII 是针对英语设计的,一个 byte 表示一个字符是够的,但是汉语有几万个字符,使用一个 byte 是远远不够的,咋办?多用 1 个字节嘛,为此发明了 UNICODE 使用 2 个字节来表示字符,兼容 ASCII,当属于 ASCII 字符时,前一个字节全为 0。

但是,又有了新的问题,对可以使用 ASCII 表示的字符使用 UNICODE 表示并不高效,每个字符都浪费了一个字节,存储空间大了一倍,假设你的源码里只有一个汉字,为了显示这个汉字,所有的英文字母都要使用 2 个字节存储,文件大小翻倍了

为了解决这个问题,发明了一些中间格式的字符集,称为通用转换格式,即 UTF(Unicode Transformation Format),常见的有 UTF-8、UTF-16、UTF-32。

UTF-8

UTF-8 怎么编码字符呢?

8 表示使用 8 bit 的块表示字符,可以使用 1 - 4 个块表示。

UTF-8 完全兼容 ASCII,使用一个 byte 表示 ASCII,怎么表示呢,其实很简单:

系统读取到的 UTF-8 编码文件是 0 和 1 的字节流,当取出一个字节(8 bit)时:

  • 如果第一位为 0,表示是一个独立的 ASCII 字符
  • 如果前两位是 1,第三位为 0,即 110,表示当前字节为两个字节表示字符的第一个字节
  • 如果前三位是 1,第四位为 0,即 1110,表示当前字节为三个字节表示字符的第一个字节
  • 如果前四位是 1,第五位为 0,即 11110,表示当前字节为四个字节表示字符的第一个字节

如果第一个 bit 位是 1,第二个 bit 位是 0,表示这个字节为多字节表示字符中的一个组成字节,因此,根据前两个 bit 是不是 10,可以判断该字节是不是字符编码的第一个字节;

如果前两位都是 11 可以确定该字节为字符编码的第一个字节,根据前四位可以判断当前字符由几个字节表示。

1st Byte 2nd Byte 3rd Byte 4th Byte Number of Free Bits Maxinum Expressible Unicode Value
0xxxxxxx 7 007F hex(127)
110xxxxx 10xxxxxx (5 + 6) = 11 07FF hex(2047)
1110xxxx 10xxxxxx 10xxxxxx (4 + 6 + 6) = 16 FFFF hex(65535)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (3 + 6 + 6 + 6) = 21 10FFFF hex(1114111)

可以看到,非首个 byte 都是使用 10 开头的,除了用作判断规则的 bit,其他 bit 都能用来表示字符,加在一起表示全世界的所有字符还绰绰有余