Unicode和字符编码总结

来源:互联网 发布:js实现5秒倒计时 编辑:程序博客网 时间:2024/05/21 08:35

之前对字符编码一直有疑惑,最近查了一些资料,也看了一些文章,在此进行简单的总结,以便日后深入学习。


Unicode是一种编码标准,它确定了涵盖所有字符的通用字符集(Universal Character Set),为世界上的每个字符都指定了唯一的数字与之对应。

 

Unicode0~0x10FFFF来映射世界上的所有字符,共有17 * ( 2 ^ 16)  = 17 * 65536 = 1114112个码位(code point),至今这些码位也只有一少部分被使用。

 

Unicode并不是具体的编码方式,虽然它规定了每个字符对应的码值,但并未规定编码后的字节序列的组织方式,基于Unicode的不同的编码方式都携带相同Unicode码值信息,但字节序列的具体内容和格式却各不相同。

 

Unicode码值共三个字节,最高字节的取值范围是0~0x10(也就是0~16),共17中可能。Unicode根据最高字节,将码值空间划分为17个层面(Plane)。0号层面称为BMPBasic Multilingual Plane,基本多文种层面),码值范围为0~0xFFFF(两个字节就可以表示BMP内的所有码值)。我们平常用到的Unicode字符一般都在BMP上。

 

Unicode中的码值0xFEFF称为BOMByte Order Mark,字节顺序标记),也称为ZWNBSPZero Width Non-Break Space,零宽非断行空格);码值0xFFFE保留不使用。

 

大小端

大端(Big Endian):高字节保存在低地址

小端(Little Endian):高字节保存在高地址

 

UCS-2

这种编码方式使用两个字节的固定长度来表示一个字符,因此它只能表示BMP中的字符

,其值是Unicode码值的低两字节。

 

UTF-16

UTF-16UCS-2类似,不同之处在于UCS-2只考虑BMP内的字符,而UTF-16采用了变长编码,每个字符的编码长度为2个字节或4个字节。对于BMP内的字符,UTF-16UCS-2相同。对于BMP以外的字符,则需要4个字节。

 

UTF-16/UCS-2以两个字节为编码单元(编码时存储二进制代码的单位),而UTF-8以字节为编码单元。

编码时,编码单元之间的顺序是确定的,但编码单元内部各字节(如果多于一个字节的话)的顺序就不一定了。这就是大小端问题,大小端问题存在于编码单元内部,而不是多个编码单元之间。

 

由于UTF-8以字节为编码单元,单元内部只有一个字节,所以不存在大小端问题。而UTF-16/UCS-2以两个字节为编码单元,所以它有大小端问题。

 

为了解决大小端问题,UTF-16/UCS-2在字节序列的最前面加上两个字节,用来标识大小端。FE FF(即BOM)表示大端,FF FE表示小端。

FEFFUTF-8编码是EF BB BF,虽然UTF-8不需要标识大小端,但在UTF-8编码的字节流前也会加上EF BB BF,用来指明该字节流使用的是UTF-8编码方式。

 

Windowstxt文件,另存为时可以选择编码方式,如果选择Unicode,那么即是什么也不写,txt文件的大小也是2字节,这两个字节就是用来标识大小端的,使用UltraEdit打开txt,并用16进制方式查看,发现这两个字节的内容是正是FF FE(说明是小端)。同理,若选择UTF-8,那么即是什么也不写,文件的大小也是3字节,以16进制查看,发现这三个字节的内容正是EF BB BF

 

Unicode -> UTF-8

UTF-8采用变长编码,根据Unicode码值的不同范围,采用不同长度的编码(1~4字节)

16进制码值

对应的UTF-8编码

码值所占位数

0000 - 007F

0XXXXXX

7bit

0080 - 07FF

110XXXXX 10XXXXXX

11bit

0800 - FFFF

1110XXXX 10XXXXXX 10XXXXXX

16bit

10000 - 10FFFF

11110XXX 10XXXXXX 10XXXXXX 10XXXXXX 

21bit

找到Unicode码值所属的区间,把码值写成二进制,替换模板中的“X”,即可得到UTF-8编码

 

Unicode -> UFT-16

设某个字符的Unicode码值是U

如果U < 0x10000,那么UUFT-16编码就是U对应的16位无符号整数

如果U >= 0x10000,则先计算U’ = U - 0x10000(易知U’的取值范围是0~0xFFFFF),然后将U’写成二进制形式:YYYY  YYYY YYXX XXXX XXXX

那么UUTF-16编码的二进制表示就是:110110YYYYYYYYYY  110111XXXXXXXXXX

为了区分2个字节的UFT-16编码和4个字节的UTF-16编码,所以2个字节的UFT-16编码不能以110110110111开头。因此,Unicode的设计者把0xD800~0xDFFF保留下来,并成为代理区。

 


1 0