我是靠谱客的博主 虚心蜜蜂,这篇文章主要介绍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编码为例,看一下对于辅助平面内的字符是如何编码的:


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 编码是:

复制代码
1
0xD950 0xDF21




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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//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; }


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 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)加码

复制代码
1
2
3
4
5
6
7
8
9
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)解码

复制代码
1
2
3
4
5
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


最后

以上就是虚心蜜蜂最近收集整理的关于C++实现unicode码转换成UTF-16的加码和解码函数的全部内容,更多相关C++实现unicode码转换成UTF-16内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部