UTF8编码中文字符存入Oracle字符集ZHS16GBK后取出展示的问题

问题现象

Oracle字符集为ZHS16GBK。
某表某字段中存入的字符串是UTF8编码(也是够了)。
直接选出查看是乱码,如下:

鎴戝氨鏄嚭鏉ユ墦閰辨补鐨勶紒

用C++等调用OCI接口选出后,可以转换编码。
用Java通过JDBC选出后,如果存在奇数汉字,则会丢失部分内容(部分乱码)。
用Toad工具查看会报Ora-29275
ORA-29275

原因与分析

可能JDBC在用选出内容时已经做了字符编码的转换(而C++等低级语言OCI接口没有)
即使是指定为二进制,指定编码方式都不行。
导致UTF8的汉字3字节编码,被当成了Ansi的2字节编码,奇数汉字最后一个字节在转换中丢失。

XXX,YYY,ZZZ -> XX,XY,YY,ZZ (丢一个Z)

解决办法

由于无法修改存入数据库时的程序,只能选出时处理。
考虑从Oracle选出内容的时候直接转换为每个字节的ASCII码(字符方式展现10进制ASCII)。
再在程序中用这些ASCII码,合成原始字符串。

SQL代码

select dump(content,1010) as content from SomeTable

选出内容将从上列中的字符串

鎴戝氨鏄嚭鏉ユ墦閰辨补鐨勶紒

变成

Typ=1 Len=30 CharacterSet=ZHS16GBK:
230,136,145,229,176,177,230,152,175,229,135,186,230,157,165,230,137,147,233,133,177,…

Hint:Dump语句的参数请查看Oracle帮助文档,也可以 dump(xx,10,yy,zz)等等。

Java代码

String s = "Typ=1 Len=30 : 230,136,145,229,176,177,230,152,175,229,135,186,230,157,165,230,137,147......";

String[] a = s.split(":");
String[] b = a[1].split(",");

byte[] c = new byte[b.length];
for (int i = 0; i < b.length; i++) {
	c[i]=(byte)Integer.parseInt(b[i].trim());
} 

String d = new String(c, "UTF-8");
System.out.println(d);

上面为简单的例子,容错等自行考虑。。。

测试结果

鎴戝氨鏄嚭鏉ユ墦閰辨补鐨勶紒

恢复正常显示:

我就是出来打酱油的!

猜你喜欢

转载自blog.csdn.net/ddrfan/article/details/85258227