这个'?'字的转换为什么是这个结果(GBK和GB18030互转)

http://www.itpub.net/thread-1164171-1-1.html

select convert('?','ZHS16GBK','ZHS32GB18030') A,
convert('?','ZHS32GB18030','ZHS16GBK') B,
convert('?','ZHS32GB18030','ZHS32GB18030') C,
dump('?') D,
dump(convert('?','ZHS32GB18030','ZHS32GB18030')) E
from dual;
-----结果如下---------------------------------------
A B C D E
? ?? ? Typ=96 Len=2: 254,159 Typ=1 Len=2: 254,159

数据库、客户端和操作系统字符集都是GBK,应用时发现这个字'?'从GB18030转码到GBK有问题,在这里进行实验。从编码看两个字符集这个字都有相同的编码FE 9F,也就是254,159。
为什么相互转换的时候会变成‘?’和‘??’,我试过编码在'?'字附近的一些其它字,发现编码为FE XX的这个区,很多字都有这个转换成问号的问题,能帮忙解释一下这个问题是怎么产生的吗。

这个问题基本弄清楚了,解释如下:
首先说字符集,GBK字符集有80个字符是后来增补的,因为需要与GB18030兼容,所以放在GB18030的PUA区(此时这80个字符也在Unicode中有自己的对应的一套编码了,这一套编码在GB18030和GBK中的映射是一致的),后来这80个字符被Unicode字符集收录,于是在Unicode中有了自己的第二套编码,但是这第二套编码是不被GBK所兼容,仅GB18030可识别,这些字符的新编码也叫非PUA编码。
简单说,这几个字符从GBK到Unicode,对应编码为A,从GB18030到Unicode,对应编码为A和A',Oracle在转换时选择的就是转为A',A'是转不回GBK编码的。这就是第一个'?出现'的原因。
做一个实验可验证:
select convert('?','ZHS16GBK','ZHS32GB18030') A,
convert(convert('?','UTF8','ZHS32GB18030'),'ZHS16GBK','UTF8') A1,
dump(convert('?','UTF8','ZHS32GB18030')) A2
from dual;
A A1 A2
-- -- ------------------------
? ? Typ=1 Len=3: 228,182,174
'?'字的Unicode的非PUA编码是4DAE,换算成UTF8的编码方式是11100100 10110110 10101110,刚好是228,182,174

而且从转换结果看,我们有理由相信Oracle在进行convert时是把源字符集的字符先转换到Unicode字符集,然后再转换到目标字符集。
再做另一个实验:
select
dump(convert('?','ZHS32GB18030','ZHS16GBK')) B,
dump(convert(convert('?','UTF8','ZHS16GBK'),'ZHS32GB18030','UTF8') )B1,
dump(convert('?','UTF8','ZHS16GBK')) B3
from dual;
B B1 B3
-------------------------- -------------------------- ------------------------
Typ=1 Len=4: 131,54,207,57 Typ=1 Len=4: 131,54,207,57 Typ=1 Len=3: 238,161,163

确实B和B1两种转换结果相同。另外对原贴中的'??'的解释,我们从B3的结果看,从GBK转换到UTF8时,转换后的UTF8编码对应的Unicode编码为E863,转换结果是正确的。而从E863转换到GB18030时结果是131,54,207,57,这个换算后对应的编码是8336 CF39,对应不到任何GB18030的字符,所以显示'??',但具体131,54,207,57是如何产生的,我还没有确切弄明白,可能是Oracle的BUG,也可能是对PUA区选择的问题。
以下是那80个字以及对应的GBK编码(GB18030编码也相同),PUA编码和非PUA编码(这两个是Unicode编码)
汉字 GBK编码 PUA编码 非PUA编码
? FE50 E815 2E81
? FE51 E816 20087
? FE52 E817 20089
? FE53 E818 200CC
? FE54 E819 2E84
? FE55 E81A 3473
? FE56 E81B 3447
? FE57 E81C 2E88
? FE58 E81D 2E8B
? FE59 E81E 9FB4
? FE5A E81F 359E
? FE5B E820 361A

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23590362/viewspace-1056221/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/23590362/viewspace-1056221/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值