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-32,UTF-16,和UTF-8。后面的数字表明至少使用多少个比特位(Bit)来存储字符,其实就是编码单元(code unit)的长度。
每种编码方式将Unicode代码点U+0000..U+D7FF和U+E000..U+10FFFF映射成唯一的编码单元序列。
UTF-32编码方式
编码单元是 32-bit,每个Unicode代码点对应一个编码单元。 特点:定长,字符的编码值与代码点的值相等,识别字符时不需要转换,有些浪费存储空间。
UTF-16编码方式
编码单元是16-bit,每个Unicode代码点对应1到2个编码单元。如果编码单元序列是110110开头,说明该序列由2个编码单元组成。
Java语言中的String类型使用的就是UTF-16编码,其编码格式如下:
| Unicode 编号 | UTF-16 编码 |
|---|---|
| xxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxx |
| 000uuuuuxxxxxxxxxxxxxxxx | 110110wwwwxxxxxx 110111xxxxxxxxxx |
其中:wwww = uuuuu - 1 |
特点:不定长,在进行字符识别时,需要进行转换。
UTF-8编码方式
编码单元是 8-bit,每个Unicode代码点对应1到4个编码单元。如果编码单元序列由2个1开头,说明该序列由2个编码单元组成,以此类推。其编码规则如下:
| Unicode 编号 | 首字节 | 第二字节 | 第三字节 | 第四字节 | 说明 |
|---|---|---|---|---|---|
| 00000000 0xxxxxxx | 0xxxxxxx | 单字节,与ASCII 编码一致 | |||
| 00000yyy yyxxxxxx | 110yyyyy | 10xxxxxx | 第一字节有两个连续的1 | ||
| zzzzyyyy yyxxxxxx | 1110zzzz | 10yyyyyy | 10xxxxxx | 第一字节有三个连续的1 | |
| 000uuuuu zzzzyyyy yyxxxxxx | 11110uuu | 10uuzzzz | 10yyyyyy | 10xxxxxx | 第一字节有四个连续的1 |
特点:
- 不定长,在进行字符识别时,需要进行转换。
- 处理字符时效率低,比如要查找字符串中的第n个字符时,必须从头开始挨个找。
- 节省存储空间和网络流量,兼容ASCII 编码。
编码方式示例
| 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-16和UTF-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)用来标识是大端还是小端。