Unicode 字符编码

2,924 阅读4分钟

Unicode标准

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

Unicode标准是一个字符编码系统,它的目标是为世界上所有的字符提供一个唯一的编码。

Unicode的开发结合了国际标准化组织所制定的ISO/IEC 10646,即通用字符集(Universal Coded Character Set ,UCS)。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。后面的数字表明至少使用多少个比特位(Bit)来存储字符,其实就是编码单元(code unit)的长度。

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

UTF-32编码方式

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

UTF-16编码方式

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

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

Unicode 编号UTF-16 编码
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
000uuuuuxxxxxxxxxxxxxxxx110110wwwwxxxxxx 110111xxxxxxxxxx
其中:wwww = uuuuu - 1

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

UTF-8编码方式

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

Unicode 编号首字节第二字节第三字节第四字节说明
00000000 0xxxxxxx0xxxxxxx单字节,与ASCII 编码一致
00000yyy yyxxxxxx110yyyyy10xxxxxx第一字节有两个连续的1
zzzzyyyy yyxxxxxx1110zzzz10yyyyyy10xxxxxx第一字节有三个连续的1
000uuuuu zzzzyyyy yyxxxxxx11110uuu10uuzzzz10yyyyyy10xxxxxx第一字节有四个连续的1

特点

  • 不定长,在进行字符识别时,需要进行转换。
  • 处理字符时效率低,比如要查找字符串中的第n个字符时,必须从头开始挨个找。
  • 节省存储空间和网络流量,兼容ASCII 编码。

编码方式示例

Code PointEncoding Form CodeEncoding Forms
U+004DUTF-320000004D
U+004DUTF-16004D
U+004DUTF-84D
U+0430UTF-32430
U+0430UTF-16430
U+0430UTF-8D0B0
U+4E8CUTF-3200004E8C
U+4E8CUTF-164E8C
U+4E8CUTF-8E4BA8C
U+10302UTF-3210302
U+10302UTF-16D800DF02
U+10302UTF-8F0908C82

编码方案(Unicode Encoding Schemes)

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

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

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

Encoding SchemeEndian OrderBOM Allowed?
UTF-8N/Ayes
UTF-16Big-endian or little-endianyes
UTF-16BEBig-endianno
UTF-16LELittle-endianno
UTF-32Big-endian or little-endianyes
UTF-32BEBig-endianno
UTF-32LELittle-endianno

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

相关资料

unicode.org/faq/utf_bom…

en.wikipedia.org/wiki/Unicod…

www.unicode.org/versions/Un…