ASCII码-Unicode码

ASCII码

从0到255都是ASCLL码
美国信息交换标准代码(American Standard Code For Information Interchange)

Unicode

Unicode 编码包含 ASCII
前面127的完全一样
称为万国码

Unicode(统一码、万国码、单一码)于1990年开始研发,1994年正式公布,是计算机领域里一项业界标准,包括字符集,编码方案等。Unicode是为了解决传统字符编码方案的局限而产生的,为每种语言中的每个字符都设定了统一唯一的二进制编码,以实现跨语言、跨平台进行文本转换、处理的要求。

计算机在设计时采用8个比特(bit)作为一个字节(byte),所以一个字节最多能表示256个字符,早期对于使用英文的西方国家来说,一个字节可以存储大小写英文字母、数学和一些符号,因此使用一个字节来制作码表(ASCII)。后来计算机传到了其他的国家,很多国家都是使用自己的语言,比如中文、日文、韩文…语言复杂了,为了解决这个问题,每个国家制定自己的码表,中国在1980年便制定了GB2312汉字编码字符集,汉字比英文多很多,一个字节明显不够用,所有就使用2个字节来编码。然而不同国家所定义的字符编码虽然可以使用,但是在不同的国家间却经常出现不兼容的情况。如果电脑想处理多语言环境(使用中文或其他语言)可能存在无法同时支持多语言环境。

为了统一所有文字的编码,产生了Unicode,把所有语言的都统一到一套编码里,这样就不会乱码了。

在表示Unicode字符时,通常会用U+然后紧跟一组16进制的数字表示一个字符,在基本多文种平面(第零平面)Basic MultilingualPlane(BMP)里所有的字符都使用4位16进制表示。编码从U+0000到U+FFFF,共支持6万多个字符,在BMP以外的字符则需要使用5位或者6位16进制来表示。

目前Unicode字符分为17组编排,0x0000至0x10FFFF,每组称为平面(Plane),每个面拥有65536个码位,共1114112个。

Unicode就像一张表,包所有的字符都编写到表中,每一个字符对应一个数字,称为码点(code point),这个数字一般不直接使用,通过不同的编码方式来使用。

UTF-8、UTF-16、UTF-32就是将数字转换到程序数据的编码方案。UTF是“UnicodeTransformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。

UTF-8

UTF-8是以字节位单位对Unicode编码,第0-127位字符使用1个字节来表示,和ASCII编码相同,从128号开始的字符使用2、3、4位字节来表,UTF-8又被称为可变长编码。

UTF-8编码中,使用的是变成的字节序列表示字符,字符对应的代码点(code point)可能使用的是1-4个字节,这样一个字节就是一个代码单元。一个代码点(code point)可能由1-4个代码单元(code unit)组成。

十进制 Unicode编码 UTF-8字节流
0-127位 0x000000-0x00007F 0xxxxxxx(7位)
128-2047位 0x000080-0x0007FF 110xxxxx 10xxxxxx(11位)
2048-65535位 0x000800-0x00FFFF 1110xxxx 10xxxxxx 10xxxxxx(16位)
65536-1114111位 0x010000-0x10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(21位)

比如:“汉”在Unicode中的编码为0x6C49,在表格中的第三行,使用模板为:1110xxxx 10xxxxxx10xxxxxx。将0x6C49转换成二进制:0110 1100 0100 1001,将模板中的x依次替换11100110 10110001 10001001,即E6 B1 89。

UTF-16

UTF-16也是可变长度编码,使用2个或者4个字节来存储字符,但是会浪费存储空间。

UTF-16编码中,字符对应的代码点(code point)可能使用的是2或4个字节,因此2个字节就是一个代码单元(code unit),一个代码点(codepoint)可由1个或者2个代码单元(code unit)组成。

十进制 Unicode编码 UTF-16字节流
0-65535位 0x000000-0x00FFFF xxxxxxxx xxxxxxxx(16位)
65536-1114111位 0x010000-0x10FFFF 110110yy yyyyyyyy 110111xx xxxxxxxx(20位)

平面0有一个专用区:0xE000-0xF8FF,有6400个码位。平面0的0xD800-0xDFFF,共2048个码位,是一个被称作代理区(Surrogate)的特殊区域。代理区的目的用两个UTF-16字符表示BMP以外的字符。所有大于0x00FFFF的码需要使用代理区的码点。

为了将一个16位无符号整数的UTF-16编码与二个16位无符号整数的UTF-16编码区分开来,Unicode编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):

十进制 Unicode编码 说明 说明
55296-56191 0xD800-0xDB7F(896个) High Surrogates 高位替代
56192-56913 0xDB80-0xDBFF(128个) High Private Use Surrogates 高位专用替代
56320-57343 0xDC00-0xDFFF(1024个) Low Surrogates 低位替代

增补的16个平面(第2平面-第17平面),范围为:0x010000-0x10FFFF,需要使用2个代理码元表示,第一个码元为0xD800-0xDBFF(高位)范围是:11011000 00000000到11011011 11111111,第二个码元为0xDC00-0xDFFF(低位)范围是:11011100 00000000到11011111 11111111。

目前Unicode最大的码位是0x10FFFF,减去0x010000后最大值为0xFFFFF,完全可以用20位来表示。

把Unicode编码记作U,如果U≥0x10000,我们先计算U’=U-0x10000,然后将U’写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy110111xxxxxxxxxx

比如:Unicode编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:

1101100001000011 1101110000110000,即0xD8430xDC30。

UTF-32

UTF-32编码以32位无符号整数为单位。Unicode的UTF-32编码就是其对应的32位无符号整数。

UTF-32编码,一个代码点对应4个字节,因此4个字节就是一个代码单元(codeunit)。

十进制 Unicode编码 UTF-32字节流
0-111411位 0x000000-0x10FFFF xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx (32位)

比如:编码0x6C49使用UTF-32编码其结果为:0x00006C49。

字节序

字节序有两种,分别是大端(Big Endian, BE)和小段(Little Endian, LE)。根据字节序的不同,UTF-16实现为UTF-16BE和UTF-16LE,UTF-32实现为UTF-32BE和UTF-32LE。

根据字节序的不同,UTF-16可被实现为UTF-16LE或UTF-16BE,UTF-32可被实现为UTF-32LE或UTF-32BE。

Unicode编码 UTF-16LE UTF-16BE UTF32-LE UTF32-BE
0x006C49 49 6C 6C 49 49 6C 00 00 00 00 6C 49
0x020C30 43 D8 30 DC D8 43 DC 30 30 0C 02 00 00 02 0C 30

Unicode标准建议用BOM(Byte Order Mark)来区分字节序,即在传输字节流前,先传输被作为BOM的字符“零宽无中断空格”。这个字符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定义的码位,不应该出现在实际传输中。

UTF编码的BOM:

UTF编码 Byte Order Mark (BOM)
UTF-8 without BOM
UTF-8 with BOM EF BB BF
UTF-16LE FF FE
UTF-16BE FE FF
UTF-32LE FF FE 00 00
UTF-32BE 00 00 FE FF