Unicode标准编码字符集与字符编码方案UTF-8、UTF-16、UTF-32

注:通过搜集学习各大神的多篇文章加自己的理解,整理此文。

在Unicode出现之前,已经有许多种不同的标准:美国的ASCII、西欧语言中的ISO 8859-1、俄罗斯的KOI-8、中国的GB 18030和BIG-5等。这样就产生了下面两个问题:一个是对于任意给定的代码值在不同编码方案下有可能对应不同的字母;二是采用大字符集的语言其编码长度有可能不同。

Unicode

设计Unicode编码的目的就是要解决这些问题。如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码。

 Unicode 是一本很厚的字典,它将全世界所有的字符定义在一个集合里。这么多的字符不是一次性定义的,而是分区定义。每个区可以存放 65536 个字符,称为一个平面(plane)。目前,一共有 17 个平面

最前面的 65536 个字符位,称为基本平面(简称 BMP ),它的码点范围是从 0 到65535,写成 16 进制就是从 U+0000 到 U+FFFF。所有最常见的字符都放在这个平面,这是 Unicode 最先定义和公布的一个平面。剩下的字符都放在辅助平面(简称 SMP ),码点范围从 U+010000 到 U+10FFFF。

字符编码方案是从一个或多个编码字符集到一个或多个固定宽度代码单元序列的映射。UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案。

UTF-32 

UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。很明显,它是内部处理最方便的表达方式,但是,如果作为一般字符串表达方式,则要消耗更多的内存。

UTF-8

UTF-8 是目前互联网上使用最广泛的一种 Unicode 编码方式,它的最大特点就是可变长。它可以使用 1 - 4 个字节表示一个字符,根据字符的不同变换长度。编码规则如下:

1,对于单个字节的字符,第一位设为 0,后面的 7 位对应这个字符的 Unicode 码点。因此,对于英文中的 0 - 127 号字符,与 ASCII 码完全相同。这意味着 ASCII 码那个年代的文档用 UTF-8 编码打开完全没有问题。

2,对于需要使用 N 个字节来表示的字符(N > 1),第一个字节的前 N 位都设为 1,第 N + 1 位设为0,剩余的 N - 1 个字节的前两位都设位 10,剩下的二进制位则使用这个字符的 Unicode 码点来填充。

UNICODE 十六进制码点范围 UTF-8 二进制
0000 0000 - 0000 007F 0xxxxxxx
0000 0080 - 0000 07FF 110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

0xxxxxxx,把一个字节做为一个单元.就跟ASCII完全一样。由于里面有额外的标志信息,所以一个字节只能表示2的7次方128个字符,

110xxxxx 10xxxxxx.把两个字节当一个单元;两个字节只能表示2的11次方2048个字符.

1110xxxx 10xxxxxx 10xxxxxx 把三个字节当一个单元。而三个字节能表示2的16次方,65536个字符

例:“汉”的 Unicode 码点是 0x6c49(110 1100 0100 1001),通过上面的对照表可以发现,0x0000 6c49 位于第三行的范围,那么得出其格式为 1110xxxx 10xxxxxx 10xxxxxx。接着,从“汉”的二进制数最后一位开始,从后向前依次填充对应格式中的 x,多出的 x 用 0 补上。这样,就得到了“汉”的 UTF-8 编码为 11100110 10110001 10001001,转换成十六进制就是 0xE6 0xB1 0x89

UTF-16

UTF-16 编码介于 UTF-32 与 UTF-8 之间,同时结合了定长和变长两种编码方法的特点。它的编码规则很简单:基本平面的字符占用 2 个字节,辅助平面的字符占用 4 个字节。也就是说,UTF-16 的编码长度要么是 2 个字节(U+0000 到 U+FFFF),要么是 4 个字节(U+010000 到 U+10FFFF)。那么问题来了,当我们遇到两个字节时,到底是把这两个字节当作一个字符还是与后面的两个字节一起当作一个字符呢?

这里有一个很巧妙的地方,在基本平面内,从 U+D800 到 U+DFFF 是一个空段,即这些码点不对应任何字符。因此,这个空段可以用来映射辅助平面的字符。

辅助平面的字符位共有 1048576 ($2^{20}$ )个,因此表示这些字符至少需要 20 个二进制位。UTF-16 将这 20 个二进制位分成两半,前 10 位映射在 U+D800 到 U+DBFF,称为高位(H)(即1101 10xx xxxx xxxx填充),后 10 位映射在 U+DC00 到 U+DFFF,称为低位(L)(即1101 11xx xxxx xxxx填充)。这意味着,一个辅助平面的字符,被拆成两个基本平面的字符表示。

因此,当我们遇到两个字节,发现它的码点在 U+D800 到 U+DBFF 之间,就可以断定,紧跟在后面的两个字节的码点,应该在 U+DC00 到 U+DFFF 之间,这四个字节必须放在一起解读。

例如U+10437编码:

0x10437减去0x10000,结果为0x00437,二进制为0000 0000 0100 0011 0111。

分区它的上10位值和下10位值(使用二进制):0000000001 and 0000110111。

添加0xD800到上值,以形成高位:0xD800 + 0x0001 = 0xD801。

添加0xDC00到下值,以形成低位:0xDC00 + 0x0037 = 0xDC37。

字符 普通二进制 UTF-16二进制 UTF-16 十六进制
字符代码
UTF-16BE
十六进制字节
UTF-16LE
十六进制字节
$ U+0024 0000 0000 0010 0100 0000 0000 0010 0100 0024 00 24 24 00
U+20AC 0010 0000 1010 1100 0010 0000 1010 1100 20AC 20 AC AC 20
U+10437 0001 0000 0100 0011 0111 1101 1000 0000 0001 1101 1100 0011 0111 D801 DC37 D8 01 DC 37 01 D8 37 DC
? U+24B62 0010 0100 1011 0110 0010 1101 1000 0101 0010 1101 1111 0110 0010 D852 DF62 D8 52 DF 62 52 D8 62 DF

Unicode和UTF-8之间的转换

Windows平台,有一个最简单的转化方法,就是使用内置的记事本小程序notepad.exe。打开文件后,点击文件菜单中的另存为命令,会跳出一个对话框,在最底部有一个编码的下拉条。

里面有四个选项:ANSI,Unicode,Unicode big endian和UTF-8。
1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对 Windows 简体中文版,如果是繁体中文版会采用 Big5 码)。

2)Unicode编码这里指的是notepad.exe使用的 UCS-2 编码方式,即直接用两个字节存入字符的 Unicode 码,这个选项用的 little endian 格式。

3)Unicode big endian编码与上一个选项相对应。

4)UTF-8编码,也就是上面谈到的编码方法。
选择完"编码方式"后,点击"保存"按钮,文件的编码方式就立刻转换好了。

Little endian 和 Big endian

UCS-2 格式可以存储 Unicode 码(码点不超过0xFFFF)。以汉字严为例,Unicode 码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,这就是 Big endian 方式;25在前,4E在后,这是 Little endian 方式。

第一个字节在前,就是"大头方式"(Big endian),第二个字节在前就是"小头方式"(Little endian)。

那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?

Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(zero width no-break space),用FEFF表示。这正好是两个字节,而且FF比FE大1。

如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。

下表所示为几个字符不同表 

Unicode 代码点

U+0041

U+00DF

U+6771

U+10400

表示字形

UTF-32 代码单元

00000041

000000DF

00006771

00010400

UTF-16 代码单元

0041

00DF

6771

D801

DC00

UTF-8 代码单元

41

C3

9F

E6

9D

B1

F0

90

90

80

下面是所有编码对应的文件开头标志:

EF BB BF    UTF-8

FE FF     UTF-16/UCS-2, big endian
FF FF     UTF-16/UCS-2, little endian


00 00 FE FF  UTF-32/UCS-4, big-endian.
FF FE 00 00  UTF-32/UCS-4, little endian.

 

 

你可能感兴趣的:(Unicode标准编码字符集与字符编码方案UTF-8、UTF-16、UTF-32)