Unicode编码的二进制编码方案

Page content

unicode介绍

unicode 编码为世界上所有字符都分配了一个唯一的数字编号。编号范围从 0x0000000x10FFFF。编号与每个字符都一一对应。

但是 unicode 本身只规定了每个字符的编号是多少,并没有规定编号如何存储。

所以就有了多种 unicode 的二进制存储方案。

unicode 二进制存储方案

二进制的存储方案主要由以下几种:

  1. UTF-32
  2. UTF-16
  3. UTF-8

UTF-32

这种方案比较简单,UTF-32 用四个字节来表示一个字符(不论编号大小统一用四个字节来存储二进制值),即每次处理都会取四个字节为一个处理单元。

例如:“赑” 的 unicode 编号为 36177,十六进制值为:0x8d51

utf-32 二进制编码为: 00000000 00000000 10001101 01010001

因为在内存中存储数据有大小端两种模式,所以UTF-32中也有两种编码方式:

  • UTF-32BE:大端序
  • UTF-32-LE:小端序

UTF32编码的缺点:

  • 浪费存储空间:不论编号大小,统一使用4个字节表示。

UTF-16

UTF-16 使用变长字节表示

  1. 对于编号在 0x 00 00 到 0x FF FF 之间的字符(常用字符集),直接使用两个字节表示。
  2. 对于编号在 0x 1 00 00 到 0x 10 FF FF 之间的字符,需要用四个字节来表示

UTF-16 也有字节序的问题所以也有:

  • UTF-16BE :大端序

  • UTF-16LE:小端序

UTF-16 相比较 UTF-32 能够更有效的节省存储空间。

UTF-8

UTF-8 也是使用变长字节表示, 使用的字节数与 unicode 的编号大小有关,编号越小使用的字节越少,编号大的则使用的字节就越多,使用的字节个数范围从 1 个字节到 4 个字节。

unicode编号和 utf-8 使用字节数对比表:

编号范围 UTF-8 字节数
0x00 ~ 0x7F ( 0 ~ 127 ) 1
0x80 ~ 0x7FF ( 128 ~ 2047 ) 2
0x800 ~ 0xFFFF ( 2048 ~ 65535 ) 3
0x10000 ~ 0x10FFFF ( > 65535) 4

UTF-8 编码规则:

  1. 使用单字节表示的字符,字节的第一位设置为 0,后面的 7 位为这个符号的unicode编号。

    例如:

    ‘W’ 这个字符的unicode 编号为127,则使用单个字节来表示。字节的第1 位为 0,剩下的7为来表示 127 本身。则 ‘W’ 的UTF-8二进制编码为:

    0 1111111

  2. 使用n(n > 1)字节表示的字符,第一个字节的前 n 位都设置为 1,第 n+1位设置为 0,其余所有字节的前两位都设为10,剩下的所有的没有被设置的二进制位用来表示 该字符的 unicode 编号。

    例如:

    汉字:’赑‘ unicode编号为 36177 。则 UTF-8 用3 个字节来表示这个汉字。

    根据规则,有如下utf-8编码过程:

    1. 第一个字节的前 3 位都设置为 1,第 4 位设置为 0:

      1110xxxx xxxxxxxx xxxxxxxx

    2. 第 2,3 字节的前两位设置为 10:

      1110xxxx 10xxxxxx 10xxxxxx

    3. 剩下的所有二进制位 x 用来表示 unicode 编号值 36177(十进制),二进制(10001101 01010001)

      11101000 10110101 10010001

    4. 可以发现剩下的 x 都已经被用来表示 unicode 编号了。

UTF-8 的处理单元为1个字节,所以不需要考虑字节序

很显然,UTF-8 能够合理有效的利用空间来存储 unicode 字符。所以很多地方都普遍使用 UTF-8 编码。