Unicode标准以及其常见的编码⽅案
本⽂转载⾃:
Unicode标准为每⼀个字符提供⼀个唯⼀的数字,⽽不⽤区分平台、语⾔等因素。
The Unicode Standard provides a unique number for every character, no matter what platform, device, application or language.
基本概念
在开始学习之前,我们需要先了解本⽂所涉及到的⼀些基本概念。
抽象字符(Abstract character):⽤于组织、控制或者表⽰⽂本数据的信息单元。
抽象字符没有具体的形式,不应与混淆。
抽象字符不⼀定对应于⼈们所认知的“字”,不应与混淆。
不能被Unicode标准直接编码的抽象字符通常可以通过组合字符序列来表⽰。
抽象字符序列(Abstract character sequence):⼀个或多个抽象字符的有序序列。
Unicode编码空间(Unicode codespace):⼗六进制0x0~0x10FFFF之间的整数。
码位(Code point):Unicode编码空间中的任意值。
编码字符(Coded character):当抽象字符被映射或者分配到编码空间中特定的码位时,它就被称为编码字符。
码位
码位是Unicode标准中很重要的⼀个概念。它的取值范围是⼗六进制的0x0~0x10FFFF,换算成⼗进制是0~1114111,共计1114112个。
需要注意的是,⼀个单⼀的抽象字符可能对应⼀个以上的码位。例如,Ω既可以表⽰⼤写的希腊字母Omega,码位是U+03A9,也可以表⽰物理学中的欧姆符号,码位是U+2126。
>>> '\u03a9'
'Ω'
>>> '\u2126'
'Ω'
单个抽象字符也可以由⼀系列码位的序列来表⽰。例如,é的码位是U+00E9,它也可以由⼩写字母e(码位为U+0065)和(Combining Acute Accent)(码位为U+0301)组合⽽成。
>>> '\u00e9'
'é'
>>> '\u0065\u0301'
'e'
在Unicode标准中,码位的表⽰⽅法通常是使⽤它们的⼗六进制,并加上U+前缀。
码位的类型
码位的分类⽅法多种多样。我们通过下表来阐明Unicode标准使⽤的七种类型和⼀些术语。
基本类型简要描述是否分配给抽象字
符
码位范围
图形(Graphic)字母、标记、数字、标点符号、符号和空
格
是
格式(Format)不可见但是影响相邻字符。包括⾏、段落
分割符
是
控制(Control)Unicode标准以外的协议或标准定义的⽤
法
是
U+0000~U+001F,U+007F,U+0080~U+009F,共计
65个
私⽤(Private-use)Unicode标准以外的私有协议定义的⽤法是
代理 (Surrogate)永久预留给UTF-16编码⽅案不允许分配U+D800~U+DFFF,共计2048个
⾮字符(Noncharacter)永久预留给内部使⽤否
U+FDD0~U+FDEF,所有以FFFE或者FFFF结尾的码位,共
计66个
保留(Reserved)预留给将来使⽤否
我们需要格外注意代理(Surrogate)类型,理解他有助于我们学习UTF-16。它总共包含2048个码位,码位空间为U+D800~
U+DFFF。它由引发出两个新的概念:
⾼位代理(High-Surrogate):U+D800~U+DBFF范围内的码位,共计1024个。
低位代理(Low-Surrogate):U+DC00~U+DFFF范围内的码位,共计1024个。
数字转unicode编码关于它们更多的内容,稍后结合UTF-16再讨论。
编码⽅案
在介绍具体的编码⽅案之前,我们先明确⼀些新的基本概念。
Unicode标量值(Unicode scalar value):除去⾼位代理和低位代理之外,所有的Unicode码位,也就是U+0000~U+D7FF和
U+E000~U+10FFFF范围内的码位。
编码单元(Code unit):最⼩的⽐特位组合,表⽰⽤于交换或处理的编码⽂本单元。Unicode标准中定义,UTF-8使⽤8⽐特的编码单
元,UTF-16使⽤16⽐特的编码单元,UTF-32使⽤32⽐特的编码单元。
编码单元序列(Code unit sequence):⼀个或多个编码单元的有序序列。
UTF-32
UTF-32将每个Unicode标量值映射成⼀个⽆符号的32⽐特的编码单元,数值与Unicode标量值相同,这
是⼀种定长的编码⽅案。
注意,UTF-32⽆法编码U+D800~U+DFFF之间的码位,因为它们不属于Unicode标量值。
>>> '\ud800'.encode('utf32')
Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'utf-32' codec can't encode character '\ud800' in position 0: surrogates
UTF-16
UTF-16将Unicode标量值中U+0000~U+D7FF和U+E000~U+FFFF范围内的码位映射成⼀个⽆符号的16⽐特的编码单元,数值与
Unicode标量值相同。将U+10000~U+10FFFF范围内的码位映射成⼀个代理对,所谓的代理对就是上⽂提到的⾼位代理和低位代理。
UTF-16是⼀种定长和变长兼顾的编码⽅案。
下表阐明了UTF-16的编码⽅式。
Unicode标量值UTF-16
xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
000u uuuu xxxx xxxx xxxx xxxx1101 10ww wwxx xxxx 1101 11xx xxxx xxxx
Unicode标量值UTF-16
其中, wwww = uuuuu - 1
重点分析使⽤代理对的情况,⼀个代理对包含⼀个⾼位代理编码单元和⼀个低位代理编码单元,都是16⽐特的。其中⾼位代理的范围是
U+D800~U+DBFF,转换成⼆进制,它的格式应该是1101 10xx xxxx xxxx,低位代理的范围是U+DC00~U+DFFF,转换成⼆进制,它的格式应该是1101 11xx xxxx xxxx。
⾄此,我们还剩下20位可以填充。我们将码位减去U+10000,再从右到左依次填充进去,就能得到UTF-16的编码。
以字符 (Old Italic Letter Ke)为例,它的码位是U+10302,⼆进制表⽰是0000 0001 0000 0011 0000 0010,减去
U+10000(⼆进制为0000 0001 0000 0000 0000 0000),得到0000 0000 0000 0011 0000 0010。从右到左填充进模版,得到1101 1000 0000 0000 1101 1111 0000 0010,对应的⼗六进制是D800 DF02。
>>> ' '.encode('utf-16be')
b'\xd8\x00\xdf\x02'
UTF-8
UTF-8将每个Unicode标量值映射成⼀到四个⽆符号的8⽐特的编码单元,这是⼀种变长的编码⽅案。
下表阐明了UTF-8的编码⽅式。
Unicode标量值第⼀个字节第⼆个字节第三个字节第四个字节00000000 0xxxxxxx0xxxxxxx
00000yyy yyxxxxxx110yyyyy10xxxxxx
zzzzyyyy yyxxxxxx1110zzzz10yyyyyy10xxxxxx
000uuuuu zzzzyyyy yyxxxxxx11110uuu10uuzzzz10yyyyyy10xxxxxx
仍然以字符 (Old Italic Letter Ke)为例,它的码位是U+10302,⼆进制表⽰是00000001 00000011 00000010,套⽤表中的模式,得到 11110000 10010000 10001100 10000010,对应的⼗六进制是F090 8C82。
>>> ' '.encode('utf-8')
b'\xf0\x90\x8c\x82'
下表阐明了UTF-8的所有有效编码范围。
Unicode标量值范围第⼀个字节第⼆个字节第三个字节第四个字节
U+0000~U+007F00~7F
U+0080~U+07FF C2~DF80~BF
U+0800~U+0FFF E0A0~BF80~BF
U+1000~U+CFFF E1~EC80~BF80~BF
U+D000~U+D7FF ED80~9F80~BF
U+E000~U+FFFF EE~EF80~BF80~BF
U+10000~U+3FFFF F090~BF80~BF80~BF
U+40000~U+FFFFF F1~F380~BF80~BF80~BF Unicode标量值范围第⼀个字节第⼆个字节第三个字节第四个字节U+100000~U+10FFFF F480~8F80~BF80~BF
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论