C++实现unicode码转换成UTF-16的加码和解码函数


         Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的,但是在实际存储和传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式(UnicodeTransformation Format,简称为UTF)。

         对Unicode编码的主要有UTF-16BE、UTF-16LE、UTF-8、UTF-7以及UTF-32等实现方式,目前常用的实现方式是UTF-16LE、UTF-16BE和UTF-8。


UTF-16

        UTF-16是用16bit编码来表达Unicode,这样表达范围是216(即65536),也就是UTF-16的代码单元(Code Unit)为16bits。如果表达BMP内的字符,用一个UTF-16的CodeUnit就可表达,对于辅助平面内的字符,UTF-16有巧妙的设计。

        落在BMP内,从U+D800到U+DFFF之间的Code Point区段是永久保留不映射到字符, UTF-16利用这保留下来的0xD800-0xDFFF区段的CodePoint来对辅助平面内的字符的Code Point进行编码。

 

对U+0000.. U+D7FF以及U+E000.. U+FFFF的编码

        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),称作代理对(surrogatepair)。

 

 

具体方法是:

  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

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

 

UTF-16解码

hi \ lo

DC00

DC01

   …   

DFFF

D800

10000

10001

103FF

D801

10400

10401

107FF

  

DBFF

10FC00

10FC01

10FFFF

 

 

 

 

 

 


 



下面以对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




以下是据此而写的c++加码与解码的函数:

//unicode BMP之外字符  转换成UTF-16 加码函数

//DWORD v      为字符的UNICODE编码  编码值大于0XFFFF
//WORD & w1    为转换成UTF-16后的    低位代理对
//WORD & w2    为转换成UTF-16后的    高位代理对
void EnCode(DWORD v,WORD &w1,WORD &w2)
{

	DWORD vx=v-0x10000;

	WORD vh=(vx&0xFFC00)>>10;


	WORD vl=vx&0x03FF;


	w1=0xD800;
	w2=0xDC00;

	w1=w1|vh;

	w2=w2|vl;



}


// UTF-16  转换成unicode编码的      解码函数

//DWORD v      为解码后的字符的UNICODE编码  编码值大于0XFFFF
//WORD & w1    UTF-16的                     低位代理对
//WORD & w2    UTF-16的                     高位代理对
void DeCode(DWORD &w, WORD &w1, WORD &w2)
{
	w1=w1&0x3FF;
	w2=w2&0x3FF;

	w=w1<<10;
	w=w|w2;
	w+=0x10000;
}


应用举例:


(1)加码

					WCHAR str[3]; //表示一个字符
					memset(str,0,3*sizeof(WCHAR));

					dw=0x64321;  //该字符的unicode编码位于BMP之外
					WORD w1,w2;
					EnCode(dw,w1,w2);
					str[0]=w1;
					str[1]=w2;
					str[3]=0;

(2)解码

					DWORD dw=0;
					WORD w1,w2;
					w1=str[0];
					w2=str[1];         //w2!=0  否则即为BMP之内的码
					DeCode(dw,w1,w2);  //dw 为UTF-16	 所对应的unicode码值



参考资料:

http://blog.csdn.net/thl789/article/details/7506133


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清水迎朝阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值