Unicode字符集与编码

2019-05-26  本文已影响0人  buzzerrookie

本文简要介绍Unicode的相关知识,以澄清部分概念。

Unicode字符集

Unicode是一个字符集,它是所有其他广泛使用字符集的超集,包含了来自ISO/IEC 6937、ISO/IEC 8859家族、ANSI Z39.64、KS X 1001、JIS X 0208、JIS X 0212、JIS X 0213、GB 2312、GB 18030、HKSCS和CNS 11643等字符集的字符。
Unicode标准完全遵守国际标准ISO/IEC 10646:2017, Information Technology—Universal Coded Character Set (UCS)。Unicode 1.0版于1991年发布,2.0版于1996年发布,写作本文时Unicode的最新版本是12.0,其他各版本的发布历史可参考History of Unicode Release

术语定义

Unicode中的常用术语如下:

组合字符

Unicode中的每个代码点都对应一个字符,但是一个字符可以对应多个代码点,代码点与字符并不是一一映射。
以字符Á为例,它有两种表示方法:

而对字符Ệ,则有三种表示方法:

Unicode提供了许多组合字符(Combining Character或Combining Mark)修饰基本字符,正如Ệ所示,多个组合字符的顺序也可以不同。为什么会出现这样的情况呢?这是为了保证Unicode与其他字符集之间转换的简易型,如ISO 8859-1/2/3/4/9/10/14/15/16中Á的编码是C1,Unicode就使用单个代码点U+00C1表示该字符。

归一化

组合字符为字符比较带来了问题,因为看着一样的字符实际可能是由不同代码点表示的,Unicode Standard Annex #15定义了两种相等:

Normalization FAQ指出程序总是应该使用规范相等执行比较相等的操作,最简单的方法就是归一化字符串:如果字符串被转换成了归一化形式,则规范相等的串会有完全相同的二进制表示。为了使用规范相等,可以使用Unicode标准提供的NFC与NFD归一化形式。Unicode标准一共定义了四种归一化(normalization)形式:

组合字符对正则表达式的影响:如点号是匹配单个代码点,还是由基本字符和组合字符组成的整个代码点序列?在实践中,许多程序的点号匹配单个代码点,无论它代表基本字符还是组合字符,即Ệ(U+0045、U+0302和U+0323)由三个点号而不是一个点匹配。

Unicode编码形式

Unicode标准支持三种编码形式(encoding form),分别是UTF-32、UTF-16和UTF-8。UTF(Unicode Transformation Format)编码是一种从Unicode代码点到唯一字节序列的映射,Unicode标准第3.9节是UTF的正式定义。

UTF-32

UTF-32编码形式使用32位无符号代码单元表示Unicode代码点:

UTF-16

UTF-16编码形式使用单个16位无符号代码单元表示位于U+0000..U+D7FF和U+E000..U+FFFF之间的代码点,使用替代对表示U+10000..U+10FFFF之间的代码点:

代码点 代码点二进制表示 UTF-16
U+0000..U+D7FF和U+E000..U+FFFF xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
U+10000..U+10FFFF 000uuuuuxxxxxxxxxxxxxxxx 110110wwwwxxxxxx 110111xxxxxxxxxx

其中wwww = uuuuu - 1

UTF-8:

UTF-8编码形式使用1到4个无符号字节序列表示Unicode代码点:

代码点 第1个字节 第2个字节 第3个字节 第4个字节
00000000 0xxxxxxx 0xxxxxxx
00000yyy yyxxxxxx 110yyyyy 10xxxxxx
zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx

Unicode编码方案

Unicode编码方案(encoding scheme)是指Unicode编码形式的一种特定字节序列化,包括对字节顺序标记(BOM)的处理。Unicode标准支持七种编码方案:

以U+004D为例,三种编码形式的代码单元如下:

UTF-8代码单元 UTF-16代码单元 UTF-32代码单元
4D 004D 0000004D

五种编码方案如下:

UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE
4D 00 4D 4D 00 00 00 00 4D 4D 00 00 00

实现

不同的编程语言对Unicode的支持程度不同。

Java

Java语言规范指出Java使用UTF-16编码表示文本序列。各JDK版本与遵守的Unicode版本对应关系如下:

JDK版本 遵守的Unicode版本
1.1之前 1.1.5
1.1 2.0
1.1.7 2.1
1.4 3.0
5.0 4.0
7 6.0
8 6.2
9 8.0
11 10.0
12 11.0

java.text包的Normalizer类的normalize方法提供了归一化功能,支持全部四种归一化形式。

实例

UTF-8

U+0430
00000yyy yyxxxxxx
00000100 00110000

11010000
10110000

U+4E8C
zzzzyyyy yyxxxxxx
01001110 10001100

11100100
10111010
10001100

U+10302
000uuuuu zzzzyyyy yyxxxxxx
00000001 00000011 00000010

11110000
10010000
10001100
10000010

参考文献

https://www.unicode.org
http://www.oracle.com/us/technologies/java/supplementary-142654.html
http://reedbeta.com/blog/programmers-intro-to-unicode/
https://www.infoq.com/presentations/unicode-history
精通正则表达式

上一篇下一篇

猜你喜欢

热点阅读