通过本机JDBC Informix驱动程序获取错误编码的数据

时间:2013-01-31 09:06:18

标签: java jdbc encoding informix

我的Informix数据库配置为:

DB_LOCALE=pl_pl.CP1250

(使用Windows CP1250字符编码的波兰语区域设置)。

在此数据库中有一个包含VARCHAR列的表,其中大部分数据在CP1250中编码,但某些记录以UTF-8编码。我怀疑它们是由ODBC插入并错误编码的.csv import。

当我使用ODBC时,可以获取错误编码的数据。它看起来不漂亮:

nazw:┼?UKASIK

但可以显示,最终用户可以编辑此类数据。那些“奇怪的”字符是'Ł'字母的UTF-8字符。

当我使用本机JDBC驱动程序时,我无法获取此类数据。而不是String我得到了例外:

JDBC Error: -79783
IX000
Kodowanie lub zestaw kodów znaków nie są obsługiwane.

英文说明:

-79783 Encoding or code set not supported
Explanation: The encoding or code set entered in the DB_LOCALE or CLIENT_LOCALE variable is not valid.

我在Jython中创建了使用本机JDBC驱动程序和JDBC-ODBC桥连接到数据库的测试程序。我只有本机驱动程序才有例外。我还尝试通过其他JDBC getXXX()方法获取此数据以获取byte[]Stream,但它们也引发了异常。我使用JDBC URL作为:

jdbc:informix-sqli://test-informix:9088/test:informixserver=ol_testifx;DB_LOCALE=pl_PL.CP1250;CLIENT_LOCALE=pl_PL.CP1250;charSet=CP1250

服务器版本:IBM Informix Dynamic Server Version 11.50.FC4

原生驱动程序:3.70.JC5DE; major: 3; minor: 70

JDBC-ODBC桥使用的ODBC驱动程序:2.0001 (3.70.TC5DE); major: 2; minor: 1

我的问题是:

有没有办法获得这种错误编码的数据?我想看看 '?'字符而不是错误编码的字符。我不想要例外,因为它们不允许最终用户查看和纠正错误编码的数据。

2 个答案:

答案 0 :(得分:1)

我得到了IBM Polska的帮助,他们发现JDBC连接字符串 可以IFX_USE_STRENC=truehttp://www-01.ibm.com/support/docview.wss?uid=swg21502902

进行扩展

这允许JDBC获取错误编码的数据。现在我可以读到:

nazw:Przemysław
nazw:Ĺ?UKASIK

(第二条记录是波兰语字母Ł编码错误)

谢谢IBM Polska!

答案 1 :(得分:0)

如果我正确理解CP1250,那么Ł位于CP1250代码点0xA3,但对应于Unicode U + 0142 LATIN CAPITAL LETTER L WITH STROKE。 U + 0142的UTF-8编码是0xC5 0x81。 CP1250中的0xC5为Ĺ,Unicode U + 0139 LATIN CAPITAL LETTER L WITH ACUTE,但0x81未分配。

在有根据的猜测中,0x81字节导致Informix生成错误。 0x81字节不能出现在格式正确的CP1250文本中(同样地,0xC0字节和0xC1字节,只有两个,可以出现在格式良好的UTF-8文本中)。目前尚不清楚如何将格式错误的数据插入到数据库中,但可能有人在他们这样做时会错误地设置区域设置信息。

(为了增加乐趣,我在问题中看到的符号似乎是UTF-8字节0xE2 0x94 0xBC = U + 253C BOX图纸LIGHT VERTICAL AND HORIZONTAL,目前尚不清楚我怎么跟Ł有关。)

你可以做些什么来解决这个问题?好问题!

忏悔:我可以拼写JDBC - E,然后是S,然后是Q,然后是L,然后是/,然后是C?不......哦!

有一个ONCONFIG参数,EILSEQ_COMPAT_MODE,可以设置为1(并且服务器重新启动),允许其他非法字符进入数据库。这可能会有所帮助,或者说可能没有,因为它已经设置好了,这就是伪造数据首先进入数据库的方式。

如果没有,可能会有一些其他技巧会有所帮助(请在下面留言),但这是边缘情况;你不应该把伪造的数据放到数据库中,很难再把它拿回来。