utf-32/utf-16/utf-8如何解析Unicode编码呢?以及BOM的作用

一: UTF-32

这个最简单,就是字符编号的整数二进制形式,四个字节。
但有个细节,就是字节的排列顺序,如果第一个字节是整数二进制中的最高位,最后一个字节是整数二进制中的最低位,那这种字节序就叫"大端”(Big Endian, BE),否则,正好相反的情况,就叫小端”(Little Endian, LE)。对应的编码方式分别是UTF-32BE和UTE-32LE。比如

注意:之所以有大端和小端两种方式,是因为硬件读写顺序的不同。
大端:数据的高字节保存在内存的低地址中,低字节保存到内存的高地址中,和我们的阅读习惯一致;小端则相反,常用的x86结构是小端模式。采用大端方式进行数据存放符合人类的正常思维,而采用小端方式进行数据存放利于计算机处理。

可以看出,每个字符都用四个字节表示,非常浪费空间,实际采用的也比较少。

二: UTE-16

        在了解UTE-16编码方式之前,先了解一下另外一个概念——"平面"。在上面的介绍中,提到了Unicode是一本很厚的字典,她将全世界所有的字符定义在一个集合里。这么多的字符不是一次性定义的,而是分区定义。每个区可以存放65536个(2·16)字符,称为一个平面(plane)。目前,一共有17个(245)平面(65536*17=1,114,112也就是110多万),也就是说,整个Unicode字符集的大小现在是 2^21。
       最前面的65536个字符位,称为基本平面(简称BMP),它的码点范围是从0到2^16-1,写成16进制就是从U+0000到U+FEFE。所有最常见的字符都放在这个平面,这是Unicode最先定义和公布的一个平面。剩下的字符都放在辅助平面(简称SMP),码点范围从U+010000到U+10FEEE。
        基本了解了平面的概念后,再说回到 UTF-16。UTF-16编码介于UTF-32与UTF-8之间,同时结合了定长和变长两种编码方法的特点。它的编码规则很简单:基本平面的字符占用2个字节,辅助平面的字符占用4个字节。也就是说,UTE-16的编码长度要么是2个字节(U+0000到U+FFFE,也就是),要么是4个字节(U+010000到U+10FEEF)。

疑问: 那么问题来了,当我们遇到两个字节时,到底是把这两个字节当作一个字符还是与后面的两个字节—起当作一个字符呢?
为了将两个字节的UTF-16编码与四个字节的UTEF-16编码区分开来,Unicode编码的设计者将0xD800-0XDFFF保留下来,并称为代理区(Surrogate) :
辅助平面的字符位共有220个,因此表示这些字符至少需要20个二进制位。UTE-16将这20个二进制位分成两半,前10位映射在U+D800到U+DBEE,称为高代理位(H),后10位映射在U+DCO0到U+DFFE,称为低代理位(L)。这意味着,一个辅助平面的字符,被拆成两个基本平面的字符表示。

       如果U>Qx10000,我们先计算U'=U-Ox10000,然后将U'写成二进制形式: ywwI wnI KX XXXX Xx&x,u的UTF-16编码(二进制)就是:1.1.01.1.0yyyyyyyyy 1.10111xXXXXXXXXX。
      按照上述规则,Unicode编码Qx10000-0x10FFFF的UTF-16编码有四个字节,前两个字节的高6位是110110,后两个字节的高6位是110111。可见,前两个字节的取值范围(二进制)是11011000 00000000到1101101111111111,即OxD800-OXDBEF。后两个字节取值范围(二进制)是11011100 00000000到1101111111111111,即OxDCO0-OxDEEE。
       因此,当我们遇到两个字节,发现它的码点在U+D800到U+DBFE之间,就可以断定,紧跟在后面的两个字节的码点,应该在U+D.C00 到U+DFEF之间,这四个字节必须放在一起解读。

接下来,以汉字"吉"为例,说明UTE-16编码方式是如何工作的。
       汉字"吾"的Unicode码点为 0x208B7,该码点显然超出了基本平面的范围(Qx0000 - 0xFFFF),因此需要使用四个字节表示。首先用Ox208B7 - 0×10000计算出超出的部分,然后将其用20个二进制位表示(不足前面补O),结果为0001000010 1110110111。接着,将前10位映射到U+D800到U+DBEEF之间,后10位映射到U+DC00到U+DFFF 即可。U+D800对应的二进制数为-1101100000000000,直接填充后面的10个二进制位即可,得到1101100001000010,转成16进制数则为0xD842。同理可得,低位为OxDFB7。因此得出汉
字"吉"的UTE-16编码为OxD842,OxDFB7。
 

和UTF-32—样,UTF-16也有UTF-16LE和UTF-16BE之分.例如:

注意: UTF-16常用于系统内部编码,我们平常说的“Unicode编码是2个字节”这句话,其实是因为windows系统默认的unicode编码就是UTF-16,在常用基本字符上2个字节的编码方式已经够用,导致的误解,其实是可变长度的。在没有特殊说明的情况下,常说的Unicode编码可以理解为UTF-16编码,而且是UTF-16BE编码(我们在网上说把什么转换成Unicode字符,其实是转换成utf-16编码,大家不要理解错误了,Unicode只不过是一个码值)

三: UTE-8

       UTF-8就是使用变长字节表示,每个字符使用的字节个数与其Unicode编号的大小有关,编号小的使用的字节就少,编号大的使用的字节就多,使用的字节个数从1到4个不等。
具体来说,各个Unicode编号范围对应的二进制格式如下表所示

图中的x表示可以用的二进制位,而每个字节开头的1或0是固定的。
       小于128的(即Ox00-0x7E之间的字符),编码与Ascii码一样,最高位为0。其他编号的第一个字节有特殊含义,最高位有几个连续的1表示一共用几个字节表示,而其他字节都以10开头。4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位Ox10EEEE也只有21位。
对于一个Unicode编号,具体怎么编码呢?首先将其看做整数,转化为二进制形式(去掉高位的O),然后将二进制位从右向左依次填入到对应的二进制格式x中,填完后,如果对应的二进制格式还有没填的x,则设为0。

例1:  “汉""字的Unicode编码是Qx6C.49。0x6C.49在Qx0800-0XEFFFE之间,使用3字节模板:1110xXXX ,1.0xXXXXX10xXXXXx。将Ox6C49写成二进制是:01101100 0100 1001,用这个比特流依次代替模板中的x,得到:11100110 1011000110001001,即E6 B189。

例2:  Unicode编码0x20C30在0x010000-0x10FFEE之间,使用4字节模板:11110xxx,1.0xxXXxx .1.0xXxxXXX1.0xXXXxx。将Qx20.30写成21位二进制数字(不足21位就在前面补0): 0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到: 11110000 101000001011000010110000,即E0 AO B0 BO。

注意:  UTF-8和UTF-32/UTF-16不同的地方是UTF-8是兼容Ascii的,对大部分中文而言,一个中文字符需要用三个字节表示。UTF-8的优势是网络上数据传输英文字符只需要1个字节,可以节省带宽资源。所以当前大部分的网络应用都使用UTF-8编码,因为网络应用的代码编写全部都是使用的英文编写,占据空间小,网络传输速度快。(这就是为什么网站采用utf-8编码的原因)

四: 什么是BOM

       我们通常会看到这样的编码UTE-8和UTE-8+BOM,那么什么是BOM呢?


       问题:  比如一个文本软件,在打开一个文件的时候,如何判断这个文件是使用的什么编码呢,该用什么编码进行解码呢?

那么就需要通过BOM (Byte Order Mark)来指明了。


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

 注意:UTF-8不需要BOM来表明字节顺序(其没有大端小段之分),但可以用BOM来表明文件是UTF-8的编码方式。根据BON的规则,在一段字节流开始时,如果接收到以下字节,则分别表明了该文本文件的编码。而如果不是以BOM开头,那程序则会以ANSI,也就是系统默认编码读取。

问: 为什么系统默认编码是GBK,而不是Unicode编码呢?

其实究其原因还是为了节省系统资源,GBK基本上可以代表绝大多数的中文字符.

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值