作者:赵璨
这两天我们在用dbunit插IM数据库时碰到了乱码问题,初步做了研究,分享一下,可能对其他测试同学也会有点帮助。有错误的地方大家尽管指出。
一:理论
编程过程中涉及到的字符集编码问题通常涉及到这样几个因素:
1. 文件编码格式
例如XML文件通过第一行的声明指定了文件的编码格式。Java中可以通过InputStream读取文件,用InputStreamReader来对读取后的字节解码。这些在陈教兽的blog中也有(http://blog.csdn.net/linkyou/archive/2009/03/14/3990547.aspx),例如:
InputStream is = new FileInputStream("z.xml");
InputStreamReader streamReader = new InputStreamReader(is, "GBK");
当然也有用其他方式解码的,例如Dom4j等等。
2. JVM编码格式
默认的Java都是使用Unicode字符集已做到更好的国际化。因此当需要解析其他字符集的时候,我们需要进行相应的解码。例如:
String s = "abc"; byte[] b = s.getBytes("UTF-8"); |
又或者有另一种方式:
String sql = "abc"; String s2 = new String(sql.getBytes("GBK"), "ISO8859-1"); |
这个如何解释?不能直接理解为将GBK转为ISO8859-1。而是应该理解为字符串sql用GBK解码还原为原始字节数组,再用ISO8859-1解码成正确的字符串。
3. 数据库编码格式
这个又复杂了一点,就谈Oracle的字符集,分成服务端和客户端。
服务端上,us7ascii是Oracle最早支持的编码方案,是单字节编码的。现在为了支持国际化,一般都采用unicode编码了。
客户端上,是通过NLS_LANG指定编码方式的,任何发自或发往客户端的数据都是用客户端定义的字符集编码。
二:实战
好,现在回到我们的问题:
1. 为什么数据库编码为us7ascii时,我们用dbunit插数据会出现乱码?
因为:1. 我们的xml数据文件编码是UTF-8: <?xml version="1.0" encoding="UTF-8"?>
2. JVM编码默认是GBK,可能大家不同的系统会略有区别,不过应该都是Unicode双字节编码:可以通过Charset.defaultCharset()查看默认编码
3. IM数据库服务端编码是us7ascii,客户端也要用us7ascii
首先dbunit读取utf-8的文件,默认情况下却用双字节的gbk解码,然后插入到单字节编码规范的数据库中,肯定出现乱码。
2. 如何解决?
最好是编码格式统一,当然数据库的编码格式我们不能改。我们能够改的是xml文件: <?xml version="1.0" encoding="GBK"?>
Ok,现在前两步统一编码了,现在要做的是在插入数据库之前在java代码中用对应us7ascii的编码格式做一次解码,对应的编码规范是“ISO8859-1”。这里我们Dbunit的代码要做一下改进,陈洪看看,更新一下代码。
具体代码如下:
DbUnit db = new DbUnit("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@10.2.225.81:1521:asoft", "aliim", "aliim"); db.setSchema("ALIIM"); String path = "util//z.xml"; FileInputStream stream = new FileInputStream(path);
//用InputStreamReader的构造函数对读取的字节流做ISO8859-1的解码 InputStreamReader reader = new InputStreamReader(stream, "ISO8859-1");
FlatXmlDataSet dataSet = new FlatXmlDataSet(reader); DatabaseOperation.INSERT.execute(db.getConnection(), dataSet); |