Unicode 字符编码

本贴最后更新于 1551 天前,其中的信息可能已经时移俗易

Unicode 标准

Unicode 联盟成立于 1991 年,并在同年发布了第一版 Unicode 标准。

Unicode 标准是一个字符编码系统,旨在支持世界范围内不同语言和现代技术学科的书面文本的交换、处理和显示。

Unicode 的开发结合了国际标准化组织所制定的 ISO/IEC 10646,即通用字符集。Unicode 与 ISO/IEC 10646 在编码的运作原理相同,但通用字符集包含了更详尽的实现信息、涵盖了更细节的主题,诸如比特编码(bitwise encoding)、校对以及呈现等。

当前的 Unicode 标准(Unicode 12.0)定义的代码空间共包含 1,114,112 个代码点(code point),范围是 0~10FFFF

Unicode 代码空间又被分为了 17 个平面,其中包含一个基本平面(Basic Multilingual Plane)和 Unicode 2.0 新增的 16 个辅助平面。

每个平面包含 65536(2^16) 个代码点,每个代码点至少要占用占 21 个比特位。

总的来说,每个 Unicode 字符都有一个唯一的编号(代码点)。

编码方式(Unicode Encoding Forms)

一个字符的 Unicode 编码是确定的。但是在实际应用过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为 Unicode 转换格式(Unicode Transformation Format,简称为 UTF)。

Unicode 支持三种字符编码方式:UTF-32UTF-16,和 UTF-8

每种编码方式将 Unicode 代码点 U+0000..U+D7FFU+E000..U+10FFFF 映射成唯一的编码单元(code unit)序列。

UTF-32 编码方式

编码单元是 32-bit,每个 Unicode 代码点对应一个编码单元。
特点:定长,字符的编码值与代码点的值相等,识别字符时不需要转换,有些浪费存储空间。

UTF-16 编码方式

编码单元是 16-bit,每个 Unicode 代码点对应 1 到 2 个编码单元。如果编码单元序列是 110110 开头,说明该序列由 2 个编码单元组成。

Java 语言中的 String 类型使用的就是 UTF-16 编码,其编码格式如下:

Scalar Value UTF-16
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
000uuuuuxxxxxxxxxxxxxxxx 110110wwwwxxxxxx 110111xxxxxxxxxx
其中:wwww = uuuuu - 1

特点:不定长,在进行字符识别时,需要进行转换。

UTF-8 编码方式

编码单元是 8-bit,每个 Unicode 代码点对应 1 到 4 个编码单元。如果编码单元序列由 2 个 1 开头,说明该序列由 2 个编码单元组成,以此类推。其编码规则如下:

Scalar Value First Byte Second Byte Third Byte Fourth Byte
00000000 0xxxxxxx 0xxxxxxx
00000yyy yyxxxxxx 110yyyyy 10xxxxxx
zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx

特点

  • 不定长,在进行字符识别时,需要进行转换。
  • 节省存储空间,特别是对于西方语言,西方语言所用字符基本上使用一个字节就能表示。

编码方式示例

Code Point Encoding Form Code Encoding Forms
U+004D UTF-32 0000004D
U+004D UTF-16 004D
U+004D UTF-8 4D
U+0430 UTF-32 430
U+0430 UTF-16 430
U+0430 UTF-8 D0B0
U+4E8C UTF-32 00004E8C
U+4E8C UTF-16 4E8C
U+4E8C UTF-8 E4BA8C
U+10302 UTF-32 10302
U+10302 UTF-16 D800DF02
U+10302 UTF-8 F0908C82

编码方案(Unicode Encoding Schemes)

由于不同架构和操作系统计算机存在大端(Big-endian)和小端(LIttle-endian)的问题, 即:对于跨越多个字节的数据对象,在内存中需要考虑它的存储顺序。

由于 UTF-16UTF-32 编码的一个编码单元包含多个字节,因此,它们的具体编码还需要区分字节序列的顺序。因为 UTF-8 的编码单元正好是一个字节,所以对于 UTF-8 编码我们不需要考虑这个问题。

Unicode 支持 7 中编码方案,如下表所示:

Encoding Scheme Endian Order BOM Allowed?
UTF-8 N/A yes
UTF-16 Big-endian or little-endian yes
UTF-16BE Big-endian no
UTF-16LE Little-endian no
UTF-32 Big-endian or little-endian yes
UTF-32BE Big-endian no
UTF-32LE Little-endian no

其中 BOM(Byte Order Mark)用来标识是大端还是小端。

相关资料

http://unicode.org/faq/utf_bom.html
https://en.wikipedia.org/wiki/Unicode
http://www.unicode.org/versions/Unicode12.0.0/

1 操作
lingyundu 在 2020-09-29 00:24:05 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...