字符编码

Sulfonamide

本文中出现的所有数字均为自然书写(低位在右)

本文中出现的所有字节流均为小地址在左

Unicode

Unicode 标准由统一码联盟(The Unicode Consortium)制定。

Unicode 将字符与0x00xD7FF之间、0xE0000x10FFFF之间的数字一一对应。最多可以表示 1112064 个字符。

Unicode 字符通常使用 U+十六进制数表示。

代理项对

0xD8000xDFFF之间的数字用于构建代理项对(surrogates pair):

  • 0xD8000xDCFF称为高代理项(high surrogates)。
  • 0xDD000xDFFF称为低代理项(high surrogates)。

代理项对的意义是实现 UTF-16 的 2、4 字节变长存储。因此,从 Unicode 2.0 开始,代理项对被禁止对应任何字符。

在 UTF-16 的处理过程中,计算机通常将 2 个字节的 UTF-16 解码成 1 个 Unicode。代理项对的出现指示计算机需要将 4 个字节的 UTF-16 解码成 1 个 Unicode。具体的转换方式详见后文 UTF-16 BE 部分。

平面

Unicode 被划分为 0-16 共 17 个平面(plain),每个平面包含 65536 个字符。

将 Unicode 右移 2 字节即可得到所在平面的编号。

其中U+0U+FFFF所在的第 0 平面称为基本多文种平面(Basic Multilingual Plane,BMP)。

UTF

Unicode 仅仅指定了字符与数字的映射关系,并没有指定其实际存储方式。Unicode 的存储方式称为 UTF。

UTF 全称 Unicode Transform Format,是 Unicode 的转换格式。

UTF 标准由统一码联盟(The Unicode Consortium)制定。

UTF-8

UTF-8 是一种 Unicode 的 1-4 字节变长存储方式,向下兼容 ASCII(ISO-­646)。

存储方式:

#Unicodebit 容量字节流(小地址在左)
1U+0U+7F70b0xxxxxxx
2U+80U+7FF110b110xxxxx 0b10xxxxxx
3U+800U+FFFF160b1110xxxx 0b10xxxxxx 0b10xxxxxx
4U+10000U+10FFFF210b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx

编码方法:

  • 将 Unicode 转换成二进制编码。
  • 对比二进制编码的位数和 bit 容量,选择合适的编码方式。
  • 输入输出均为从右往左,依次用二进制编码填入字节流中的x,不足的位补0

例1:

  • U+5F20(字符)转换成二进制编码0b 0101 1111 0010 0000
  • 二进制编码的位数为15,选择编码方式3。
  • 0b 101 111100 100000填入,得到 UTF-8 的二进制形式0b11100101 0b10111100 0b10100000(十六进制形式0xE5 0xBC 0xA0)。

例2:

  • U+1F604(字符😄)转换成二进制编码0b 0001 1111 0110 0000 0100
  • 二进制编码的位数为17,选择编码方式4。
  • 0b 11111 011000 000100填入,得到 UTF-8 的二进制形式0b11110000 0b10011111 0b10011000 0b10000100(十六进制形式0xF0 0x9F 0x98 0x84)。

UTF-16

UTF-16 BE

这是一种 Unicode 的 2、4 字节变长存储方式。

编码方法:

  • 若 Unicode 位于U+0U+FFFF之间:

    • 按照自然顺序书写(低位在右),将 Unicode 转换成二进制编码,在左边用0将其补足成16位,然后按照 8 bit 切分字节,左侧为小地址,构成 UTF-16 BE。
  • 若 Unicode 位于U+10000U+10FFFF之间,则:

    • 减去0x10000
    • 将结果转换成二进制编码,按照自然顺序书写(低位在右)。
    • 输入输出均为从右往左,依次用二进制编码填入下列字节流中的x,不足的位补0
    • 字节流(小地址在左)0b110110xx 0bxxxxxxxx 0b110111xx 0bxxxxxxxx

代理项对:

  • 0b110110xx 0bxxxxxxxx称为高代理项(存放 Unicode 的高位),位于0xD8000xDCFF之间。
  • 0b110111xx 0bxxxxxxxx称为低代理项(存放 Unicode 的低位),位于0xDD000xDFFF之间。

例1:

  • U+5F20(字符),位于U+0U+FFFF之间。
  • 按照自然书写顺序,将结果转换成二进制编码,在左侧用0补足成16位,然后按照字节切分,构成 UTF-16 BE 的二进制形式0b01011111 0b00100000(十六进制形式0x5F 0x20)。

例2:

  • U+1F604(字符😄)位于U+10000U+10FFFF之间。
  • 减去0x10000,得0xF604,转换成二进制编码0b 0001 1111 0110 0000 0100
  • 填入二进制编码0b 111101 10 00000100,得到 UTF-16 BE 的二进制形式0b11011000 0b00111101 0b11011110 0b00000100(十六进制形式0xD8 0x3D 0xDE 0x04)。

UTF-16 LE

  • 2 字节 UTF-16:UTF-16 LE 和 UTF16-BE 完全相同。
  • 4 字节 UTF-16:首先生成 UTF-16 BE 并将其平均分为2组,然后将每组的2个字节交换位置,这样就可以得到 UTF-16 LE。

UTF-32

UTF-32 BE

这是一种 Unicode 的 4 字节定长存储方式。

编码方法:

  • 按照自然顺序书写(低位在右),将 Unicode 转换成二进制编码,在左边用0将其补足成32位,然后按照 8 bit 切分字节,左侧为小地址,构成 UTF-32 BE。

例1:

  • U+5F20(字符)转换成二进制编码0b 0101 1111 0010 0000
  • 0将其补足成32位,得到 UTF-32 BE 的二进制形式0b00000000 0b00000000 0b01011111 0b00100000(十六进制形式0x00 0x00 0x5F 0x20)。

例2:

  • U+1F604(字符😄)转换成二进制编码0b 0001 1111 0110 0000 0100
  • 0将其补足成32位,得到 UTF-32 BE 的二进制形式0b00000000 0b00000001 0b11110110 0b00000100(十六进制形式0x00 0x01 0xF6 0x04)。

UTF-32 LE

将 UTF-32 BE 整体翻转字节顺序,即可得到 UTF-32 LE。

UCS

UCS  是 Universal Character Set(通用字符集)的简称。

UCS 标准由国际标准化组织(ISO)制定。在最新标准中,UCS 将字符与0x00x10FFFF之间的数字一一对应,最多可以表示1114112个字符。

UCS 的地位等同于 Unicode,两者也基本相同(同一字符对应的 Unicode 值与 UCS 值是相等的)。不同之处在于:UCS中的0xD8000xDFFF区域有对应的字符,而 Unicode(2.0+版本)将其定义为代理项对而不对应任何字符。

UCS-2 标准与 UCS-4 标准由国际标准化组织(ISO)制定。UCS-2 与 UCS-4 都是 UCS 的存储映像,关系如同 UTF 和 Unicode。

UCS-2

UCS-2 是一种 UCS 的 2 字节定长存储方式,该标准已经过时。

UCS-2 与 UTF-16 BE 相似。两者的差别在于:UCS-2 只支持基本多文种平面,而 UTF-16 支持所有平面。

由于 UCS 与 Unicode(2.0+版本)在0xD8000xDFFF区间采用了不同的编制方法,所以 UTF-16 在兼容 UCS-2 的同时,也存在着冲突。(不过大多数软件能够将 UTF-16 中错误的代理项对当作 UCS-2 来理解,将冲突减少到最低。)

摘自 Unicode 官网 - https://unicode.org/faq/utf_bom.html#utf16-11

Q: What is the difference between UCS-2 and UTF-16?
A: UCS-2 is obsolete terminology which refers to a Unicode implementation up to Unicode 1.1, before surrogate code points and UTF-16 were added to Version 2.0 of the standard. This term should now be avoided.
UCS-2 does not describe a data format distinct from UTF-16, because both use exactly the same 16-bit code unit representations. However, UCS-2 does not interpret surrogate code points, and thus cannot be used to conformantly represent supplementary characters.
Sometimes in the past an implementation has been labeled "UCS-2" to indicate that it does not support supplementary characters and doesn't interpret pairs of surrogate code points as characters. Such an implementation would not handle processing of character properties, code point boundaries, collation, etc. for supplementary characters.

UCS-4

UCS-4 是一种 UCS 的 4 字节定长存储方式,与 UTF-32 BE 完全相同。

字节顺序

字节顺序(字节序,端序,Endianness,Byte Endianness)是指:在计算机科学领域中,是跨越多字节的程序对象的存储规则。

在几乎所有的机器上,多字节对象都被存储为连续的字节序列。而存储地址内的排列则有两个通用规则。对于一个多位的整数,如果包含最低有效位在字节存放在小地址,则称小端序(little-endian,LE);反之则称大端序(big-endian,BE)。

自然书写一个二进制/十六进制整数,按照 8 bit 切分字节,若将右侧视为小地址则为小端序。

Unicode 就是一个多位整数,因此在编码为 UTF-16 和 UTF-32 时,有 BE 和 LE 两种编码方式。由于 UTF-8 是非对称的,所以只有唯一的编码方式。

在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均要按照网络标准转化为大端序

PS:区别字节序与位序(Bit endianness)。位序指单字节内部各个位的存储规则。由于位序属于CPU架构的底层且各个计算机差别不大,因此用的非常少。本文不涉及位序。

字节顺序标记

字节顺序标记(Byte Order Mark,BOM)位于文档开头,用于文件的编码方式以及字节顺序。

编码字节流(小地址在左)
UTF-80xEF 0xBB 0xBF
UTF-16 BE 和 UCS-2 BE0xFE 0xFF
UTF-16 LE 和 UCS-2 LE0xFF 0xFE
UTF-32 BE 和 UCS-4 BE0x00 0x00 0xFE 0xFF
UTF-32 LE 和 UCS-4 LE0xFF 0xFE 0x00 0x00

示例

U+5F20 (字符

格式字节流(小地址在左)
UTF-80xE5 0xBC 0xA0
UTF-16 BE 和 UCS-2 BE0x5F 0x20
UTF-16 LE 和 UCS-2 LE0x20 0x5F
UTF-32 BE 和 UCS-4 BE0x00 0x00 0x5F 0x20
UTF-32 LE 和 UCS-4 LE0x20 0x5F 0x00 0x00

U+1F604(字符😄

格式字节流(小地址在左)
UTF-80xF0 0x9F 0x98 0x84
UTF-16 BE0xD8 0x3D 0xDE 0x04
UTF-16 LE0x3D 0xD8 0x04 0xDE
UTF-32 BE 和 UCS-4 BE0x00 0x01 0xF6 0x04
UTF-32 LE 和 UCS-4 LE0x04 0xF6 0x01 0x00
阅读 2.9k

技能树点亮中。

394 声望
11 粉丝
0 条评论

技能树点亮中。

394 声望
11 粉丝
文章目录
宣传栏