跳转至

Unicode

字符集:为每一个字符分配唯一的 ID(学名为码位/码点/CodePoint)

编码规则:将码位转换为字节序列的规则,编码/解码

Unicode是字符集,UTF-8、UTF-16、UTF-32等是具体的编码规则。

ASCII 码7位,共128字符,编码时用一个byte表示,第0位为奇偶校验位。

Unicode字符集为每一个字符分配一个码位,如的码位为30693,记作U+77E5(30693的16进制为0x77E5)。

目前的Unicode字符分为17组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个。

  • code point: 码位

  • code unit: 指某种 Unicode 编码方式里编码一个 code point 需要的最少字节数,比如 UTF-8 需要最少一个字节,UTF-16 最少两个字节,UCS-2 两个字节,UCS-4 和 UTF-32 四个字节,后面三个是定长编码。

Unicode中的U+D800~U+DFFF码点,称之为代理码点,不表示任何字符,给UTF-16使用

编码规则

UTF-16

16 位为一个编码单位,最开始用2 byte表示unicode(基本平面码点),直接将码位映射位编码。

UTF-16中,大部分汉字采用两个字节编码,少量不常用汉字采用四个字节编码。

随着unicode的增补平面码点的出现,采用代理机制进行扩展。

  • Unicode字符集基本平面BMP中的字符(除U+D800~U+DFFF码点,称之为代理码点),其编码和码点值是一样的,2 byte表示;

  • Unicode字符集增补平面中的字符,通过代理码点扩展,4 byte表示。

代理Surrogate

增补平面一共有16个平面,码点编号范围为0x10000~0x10FFFF:

  • 用两个代理码元表示,第一个码元的取值范围为0xD800~0xDBFF,第二个码元的取值范围为0xDC00~0xDFFF
======代理码点1======       ======代理码点2====== 
1101 10pp ppxx xxxx        1101 11xx xxxx xxxx
  • 总位数p + x = 20,正好为增补平面的所有码点。

  • 计算时,将unicode的码位值先减去 0x10000,再用模板填充;

UTF-8**

8 位为一个编码单位可变长编码,将一个码位编码为1到4个字节。常用字符更少字符数。

码位对应的模板
U+  000 ~ U+  007F : 0XXXXXX                                       共2^7位
U+ 0080 ~ U+  07FF : 110XXXXX 10XXXXXX                             共2^11 - 2^7
U+ 0800 ~ U+  FFFF : 1110XXXX 10XXXXXX 10XXXXXX                    共2^16 - 2^11
U+10000 ~ U+10FFFF : 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX           共2^20

的码位U+77E5位于第三行

      7    7     E    5
    0111 0111 1110 0101   二进制的77E5
 --------------------------    
    0111   011111   100101 二进制的77E5(按照模板X对齐)
1110XXXX 10XXXXXX 10XXXXXX 模板
11100111 10011111 10100101 带入模板
   E   7    9   F    A   5    

UTF-32

UTF-32编码以32位为编码单位。Unicode的UTF-32编码就是其对应的32位无符号整数。

字节序

字节序有两种,分别是“大端”(Big Endian, BE, 高字节存于内存低地址)和“小端”(Little Endian, LE, 高字节存于内存高地址)。

在将逻辑形式的码元序列(或可称之为逻辑编码)映射为物理形式的字节序列(或可称之为物理编码)时,因系统平台的差异,存在一个字节序(Byte-Order字节顺序)的问题。

Unicode标准建议用BOM(Byte Order Mark)来区分字节序,其值为 U+FEFF(特定的用途的unicode)。

  • 字节FE(二进制为1111 1110)FF(二进制为1111 1111)在 UTF-8 编码中永远不会出现,称之为零宽度不中断空格(ZERO WIDTH NO-BREAK SPACE);

接收到 FEFF 表示大端,接收到 FFEF 表示小端。

UTF-8 不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE“的UTF-8编码EF BB BF。但,最好不要使用,防止无法识别。

Unicode编码 0x 00 6C 49 0x 02 0C 30
UTF-16LE FF FE 49 6C FF FE 30 DC 43 D8
UTF-16BE FE FF 49 6C FE FF D8 43 DC 30
UTF-32LE FF FE 00 00 49 6C 00 00 FF FE 00 00 30 0C 02 00
UTF-32LE 00 00 FE FF 00 00 6C 49 00 00 FE FF 00 02 0C 30

网络字节序是大端字节序