Dom4j方式解析XML乱码问题详解

1.  引起乱码的原因

现象:将内存中的Document对象保存到持久化设备生成XML文件后,XML文件无法正常打开,出现乱码。
表面原因:因为XML文件的真正格式(即XML文件保存在持久化设备上的编码格式)和XML文档声明的encoding属性值不一致。
深层原因:一个没有问题的XML文件(XML文件的真正的编码格式和encoding属性值一致),Dom4J API都可以把这个XML文件正常解析成一个Document对象。不管这个XML文件在读入内存之前是什么编码格式,在内存中形成的Document对象都是UTF-8格式,并且encoding属性值也相应的变成UTF-8。造成 XML文件的真正格式和 encoding属性值不一致的情况发生在把Document对象写入持久化设备时字符到字节的转换过程或字符流直接存储过程。

2.  错误分析

(1)字符流写入
XMLWriter writer = new XMLWriter(new FileWriter(xmlFilePath));
writer.write(document);
writer.close();
问题分析:FileWriter不能指定字符编码,它会按本地计算机环境默认的编码(中文windows一般是GB2312)把内存中的 Document对象(UTF-8编码,encoding=“UTF-8”)转换成GB2312编码的字符流存入持久化设备,此时文件的真正格式为GB2312,encoding依旧为UTF-8,故出现乱码。
(2)转换流写入
XMLWriter writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(xmlFilePath),"GB2312")); 
writer.write(document);
writer.close();
问题分析:转换流指定了编码格式把 内存中的 Document对象(UTF-8编码,encoding=“UTF-8”)转换成字节流,如果指定的编码格式是GB2312,则 此时文件的真正格式为GB2312,encoding依旧为UTF-8,故出现乱码。如果将指定的编码格式指定为UTF-8格式,不会出现乱码。

3.  解决办法

(1)转换流写入
XMLWriter writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(xmlFilePath),"UTF-8")); 
writer.write(document);
writer.close();
缺点:转换流指定的编码格式为UTF-8格式,故持久化的XML文件 的真正格式 只能是UTF-8,encoding属性值为UTF-8。
(2)使用OutputFormat——终极解决办法
OutputFormat format = OutputFormat.createPrettyPrint(); 
format.setEncoding("GB2312");
XMLWriter writer = new XMLWriter(new FileOutputStream(xmlFilePath), format);
writer.write(document);
writer.close();
生成一个漂亮的格式化输出器(紧缩的格式化输出器也可以)对象 format, 设置其编码格式为自己想要的任意格式。输出时, format会先把内存中的 Document对象的encoding属性值改为设置的编码格式,然后再把 Document对象按设置的编码格式格式化字节流。 此时XML文件的真正格式和encoding属性值一致,不会出现乱码。
注:构造 XMLWriter对象的输出流对象必须是字节流对象,如果是字符流对象又会导致Document对象多次按不同编码转换,可能又会出现乱码问题。

你可能感兴趣的:(XML技术)