该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-03-31
DB: mysql_4.0.18 JDBC:mysql-connector-java-3.0.11-stable-bin.jar 在jvm环境中,程序向mysql中写中文字符串,大部分的\n都工作得很好。例如保存“你好\n你好”,出来的效果是: 你好 你好 但要是保存“列表\n你好”,显示出来的效果: 列表\n你好 我发觉只要\n的前面是“表”或“哥”就一定有这个问题。这是mysql jdbc的问题?(对它确实没有什么信心) 知道原因的朋友可否指点个方向? 附: 保存"列表\r\n你好",结果为: 列表\r 你好 直接在一些非jvm环境,如loadSQL中,跑sql语句:insert into xxx values('列表\n你好'),正常。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-03-31
我猜想和我以前碰到的问题差不多:
原文见我的 blog : http://blogsite.3322.org:8080/jspwiki/Wiki.jsp?page=Main_blogentry_140803_1 为了解决中文问题,在 JDBC 的 URL 中加了一句话: ?useUnicode=true&characterEncoding=GBK 就因为这句话,搞死我了。 PreparementStatement? 的 setString 当中,如果有 \ 的话,会被保存为两个 \,如果这个字符串当中有 ' 的话,就根本没法写入到数据库当中。花了整天的时间看 JDBC 的源码,发现它把 \' 前面的反斜线又做了 Escape,而没有 Escape ',所以造成了问题。将 GBK 换成 GB2312 就好了。在 StringUtils? 当中有这么一句话: if (encoding.equalsIgnoreCase("SJIS"); || encoding.equalsIgnoreCase("BIG5"); || encoding.equalsIgnoreCase("GBK");); { b = escapeSJISByteStream(b);; } 这是造成问题的罪魁祸首。 |
|
返回顶楼 | |
发表时间:2004-03-31
非常感谢!
我把gbk改为gb2312,的确解决问题。佩服你们可以在没有适当提示的情况下,仍可追查到原因。虽然我也怀疑到了mysql jdbc 但细想一下,问题似乎又不完全一样。我说的情况,只发生在某些特定中文之后,对于大部分中文来说,还是很正常的。似乎多不多加一个\,依赖于它前面的字符。 |
|
返回顶楼 | |
发表时间:2004-03-31
SimonLei 写道 PreparementStatement? 的 setString 当中,如果有
\ 的话,会被保存为 \\,如果这个字符串当中有\' 的话,就根本没法写入到数据库当中。花了整天的时间看 JDBC 的源码,发现它把 \' 前面的反斜线又做了 Escape,即\\',而没有 \',所以造成了问题。将 GBK 换成 GB2312 就好了。 是不是这样会好一些? |
|
返回顶楼 | |
发表时间:2004-03-31
StringUtils.java中的相关代码,看不明。
/** * Unfortunately, SJIS has 0x5c as a high byte in some of its double-byte * characters, so we need to escape it. * * @param origBytes the original bytes in SJIS format * @param origString the string that had .getBytes(); called on it * @param offset where to start converting from * @param length how many characters to convert. * * @return byte[] with 0x5c escaped */ public static byte[] escapeSJISByteStream(byte[] origBytes, String origString, int offset, int length); { if ((origBytes == null); || (origBytes.length == 0);); { return origBytes; } int bytesLen = origBytes.length; int bufIndex = 0; int strIndex = 0; ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(bytesLen);; while (true); { if (origString.charAt(strIndex); == '\\'); { // write it out as-is bytesOut.write(origBytes[bufIndex++]);; //bytesOut.write(origBytes[bufIndex++]);; } else { // Grab the first byte int loByte = (int); origBytes[bufIndex]; if (loByte < 0); { loByte += 256; // adjust for signedness/wrap-around } // We always write the first byte bytesOut.write(loByte);; // // The codepage characters in question exist between // 0x81-0x9F and 0xE0-0xFC... // // See: // // http://www.microsoft.com/GLOBALDEV/Reference/dbcs/932.htm // // Problematic characters in GBK // // U+905C : CJK UNIFIED IDEOGRAPH // // Problematic characters in Big5 // // B9F0 = U+5C62 : CJK UNIFIED IDEOGRAPH // if (((loByte >= 0x81); && (loByte <= 0x9F);); || ((loByte >= 0xE0); && (loByte <= 0xFC););); { if (bufIndex < (bytesLen - 1);); { int hiByte = (int); origBytes[bufIndex + 1]; if (hiByte < 0); { hiByte += 256; // adjust for signedness/wrap-around } // write the high byte here, and increment the index // for the high byte bytesOut.write(hiByte);; bufIndex++; // escape 0x5c if necessary if (hiByte == 0x5C); { bytesOut.write(hiByte);; } } } else if (loByte == 0x5c); { if (bufIndex < (bytesLen - 1);); { int hiByte = (int); origBytes[bufIndex + 1]; if (hiByte < 0); { hiByte += 256; // adjust for signedness/wrap-around } if (hiByte == 0x62); { // we need to escape the 0x5c bytesOut.write(0x5c);; bytesOut.write(0x62);; bufIndex++; } } } bufIndex++; } if (bufIndex >= bytesLen); { // we're done break; } strIndex++; } return bytesOut.toByteArray();; } |
|
返回顶楼 | |
发表时间:2004-04-01
thatway 写道 SimonLei 写道 PreparementStatement? 的 setString 当中,如果有
\ 的话,会被保存为 \\,如果这个字符串当中有\' 的话,就根本没法写入到数据库当中。花了整天的时间看 JDBC 的源码,发现它把 \' 前面的反斜线又做了 Escape,即\\',而没有 \',所以造成了问题。将 GBK 换成 GB2312 就好了。 是不是这样会好一些? 没错没错,我的 weblog 自动过滤了一个 \ :$ |
|
返回顶楼 | |
发表时间:2004-04-09
所有的原因都是由于StringUtils.java的escapeSJISByteStream()方法引出来的。
它在处理的过程中,有两个index,一个是bufIndex,一个是stringIndex。对于中文(双字节)来说,bufIndex = stringIdex的两倍。 写中文时越界就是因为这两个index的增长不同步。 原方法中只处理了低字节在区间0x00-0x80、0x81-0x9F和0xE0-0xFC的中文字,在这些区间中,bufIndex +2 时,stringIndex才+1,是同步的。 但在其它区间,bufIndex的增长和stringIndex的增长并不同步,bufIndex+1,而stringIdex又+1。 修改见附件。 但问题还没有解决。(几天都没上来把它更新好,抱歉) 修改后,我认为,我已经真正实现了设计原本的意途了,但是即引发更多的问题。举例说,byte为[80,5c]的GBK汉字,转化后会变成[80,5c,5c]。如果这个汉字在一句SQL的结束,即单引号"'"前,MYSQL将会报SQL语法错误。 我再尝试把[80,5c]不经转换,直接出入MYSQL,没发现任何错误。 于是,最后我干脆就把GBK编码的的直接出入库,不作任何转换了。 注:本文有一个前提,MYSQL数据库的默认编码为GBK,这也许是一个关键。但我没有测试。 |
|
返回顶楼 | |
发表时间:2004-07-12
3.0.10的版本好像没问题
|
|
返回顶楼 | |
发表时间:2004-07-12
没用过3.0.10,但用过3.0.11,还是一样。StringUtils.java没有修改
|
|
返回顶楼 | |
发表时间:2004-07-13
我的意思是,我用3.0.11也有问题,后来尝试改回了3.0.10,就没问题了。
|
|
返回顶楼 | |