Chinaunix首页 | 论坛 | 博客
  • 博客访问: 125778
  • 博文数量: 42
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 354
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-01 15:34
个人简介

不晓得说啥子

文章分类

全部博文(42)

文章存档

2015年(41)

2014年(1)

我的朋友

分类: C/C++

2015-04-11 20:17:53

UTF-16简介:    

     UTF-16是(0x0 -- 0x10FFFF字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为 "storage format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数(即)的序列,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示(两个字节或者四个字节),因此这是一个变长表示。

        UTF-16是用16bit编码来表达Unicode,这样表达范围是216(即65536),也就是UTF-16的代码单元(Code Unit)为16bits。如果表达BMP内的字符,用一个UTF-16的Code Unit就可表达,对于辅助平面内的字符,UTF-16有巧妙的设计。落在BMP内,从U+D800U+DFFF之间的Code Point区段是永久保留不映射到字符, UTF-16利用这保留下来的0xD800-0xDFFF区段的CodePoint来对辅助平面内的字符的Code Point进行编码。所以可以将unicode对应的字符编码表分解为两部分: U+0000...U+D7FF  (U+D800....U+DFFF(保留,用作四个字节编码的代理))  U+E000.. U+FFFF          U+10000.. U+10FFFF

                                 

UTF-16编码:

对U+0000.. U+D7FF以及U+E000.. U+FFFF的编码(不包含U+D800U+DFFF

        UTF-16与UCS-2对这个范围内的CodePoint进行编码,采用单个16bit长的CodeUnit,数值等价于对应的Code Point。BMP中的这些Code Point是仅有的可以被UCS-2表示的Code Point。

对U+10000.. U+10FFFF的编码

        辅助平面(Supplementary Planes)中的CodePoint,在UTF-16中被编码为一对16bit长的Code Unit(即32bit,4Bytes),称作代理对(surrogate pair)。


 具体方法是:

UTF-16解码

hi \ lo

DC00

DC01

   …   

DFFF

D800

10000

10001

103FF

D801

10400

10401

107FF

  ?

?

?

?

?

DBFF

10FC00

10FC01

10FFFF

  1. Code Point减去0x10000, 得到的值是长度为20bit(0..0xFFFFF);
  2. 步骤1得到数值的高位的10比特的值(值范围为0..0x3FF)被加上0xD800得到第一个Code Unit或称作高位代理(high surrogate)或前导代理(lead surrogate)。取值范围是0xD800..0xDBFF
  3. 步骤1得到数值的低位的10比特的值(值范围为0..0x3FF)被加上0xDC00得到第二个Code Unit或称作低位代理(low surrogate)或后尾代理(trail surrogate)。取值范围是0xDC00..0xDFFF

        这样,这个范围内的字符就被编码成了一个代理对[lead surrogate,trail surrogate]:两个16bits的Code Unit,取值范围分别是0xD800..0xDBFF和0xDC00..0xDFFF。而BMP中得到的Code Unit的范围是0x0000..0xFFFF(0xD800..0xDFFF是保留的,不包含其中),所以这三个区段是相互不重叠的,在解码时很容易实现。

        UTF-16解码[高位代理+低位代理]得到的Code Unit对与Code Point的对应关系如上表所示。



下面以对U+64321的UTF-16编码为例,看一下对于辅助平面内的字符是如何编码的:

V  = 0x64321

Vx = V - 0x10000

     = 0x54321

     = 01010100 0011 0010 0001

 

Vh = 01 0101 0000 // Vx 的高位部份的 10 bits

Vl  = 11 0010 0001 // Vx 的低位部份的 10 bits

w1 = 0xD800           // 结果的前16位元初始值

w2 = 0xDC00          // 结果的后16位元初始值

 

w1 = w1 | Vh

   = 1101 1000 0000 0000

     |             01 0101 0000

   = 1101 1001 0101 0000

   = 0xD950

 

w2 = w2 | Vl

   = 1101 1100 0000 0000

    |              11 0010 0001

   = 1101 1111 0010 0001

   = 0xDF21

        所以,这个字 U+64321 最终的 UTF-16 编码是:

0xD950 0xDF21



UTF-16解码:
     用W1表示第一个UTF-16  Code Unit
     1、判断是否 0x0000 =< W1 <=0xD7FF 或者是 0xE000 =< W1 <= 0xFFFF,如果满足则是在BMP范围内的编码,直接的出相应的unicode编码就可以
     2、否则判断是否  0xD800 =< W1 <= 0xDBFF ,取W2为W1后的一个Code Unit(如果不存在则说明编码有错误),判断是否0xDC00 =< W2 <= 0xDFFF,如果满足条件(不满足则编码有错误)
           (( W1 & 0x03FF) << 10) | ( W2 & 0x03FF) + 0x10000便可以得到unicode编码的字符

 如  0xD950 0xDF21   
          W1 = 0XD950 = 1101 1001 0101 0000
          W2 = 0xDF21 =  1101 1111 0010 0001
W1不满足条件1,则继续判断条件2,  0xD800 =< 0XD950 <= 0xDBFF  并且 0xDC00 =<0xDF21<= 0xDFFF
          w1 = (W1 & 0x03FF)<<10 = 0101 0100 0000 0000 0000
          w2 ( W2 & 0x03FF)          = 11 0010 0001
          u = (w1 |  w2)                     =0101 0100 0011 0010 0001
          u + 0x10000                      =  0x64321
     

与UTF-8编码相比,UTF-16编码采用两个字节或者四个字节编码,大多数的码字编为两个字节,这样在一定程度上节省了空间,但是UTF-16编码并不能表示ASCII编码,而UTF-8编码采用1个字节到6个字节来对unicode进行编码,所以也可以刻ASCII编码兼

阅读(3217) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~