dom4j⽣成xml⽂件,解析后出现中⽂乱码问题
背景(可以忽略)
项⽬在本地写完了,和队友测试都通过了,最后部署到云端,云端服务器是Windows Server 2008 R2 Standard操作系统,部署到云端后再次和队友测试⼀下,就出现了问题。
问题描述
云端服务器上使⽤dom4j⽣成l⽂件,⽂件内容包含中⽂。使⽤EditPlus软件打开,部分内容如下:
队友使⽤android设备下载该⽂件并来解析,错误发⽣了:最终解析内容成功,但是发现解析出来保存到数据库的中⽂内容是乱码
解决
1.推给队友
我的思考:我部署本地给你提供服务时你那边解析是正常的,我放到云端没有做任何修改,你那边是不是修改了,你看⼀下。
打脸:我让队友检查⼀下是不是你那边解析数据库的字符编码不是utf-8,或者你读的时候是不是设置了编码,队友就按照我的思路去检查,她说她的代码也没有变。
为了验证,她还把我们之前在项⽬部署在本地时⽣成的l⽂件放到android中解析,解析后得到的内容没有乱码。
队友提⽰:你的⽂件内容是utf-8,但是你的⽂件保存到磁盘上上的编码是utf-8吗?
2.对⽐发现问题
我把之前在本地服务器上⽣成的l和在云端服务器⽣成的l进⾏了对。
上⾯图⽚是云端⽣成的l⽂件,下⾯是之前在本地⽣成的l部分内容:
发现问题
两份⽂件内容都⼀样,声明编码格式encoding都是UTF-8,不同是两份⽂件保存在磁盘上的编码不同,云端是GBK(显⽰是ANSI),本地服务器保存的是UTF-8。问题就是⽂件声明的内容的编码和保存到磁盘上使⽤的编码不⼀致(?),⾄于具体的原理下⾯会解释。
云端:encoding=UTF-8 保存编码:GBK
本地服务器端:encoding=UTF-8 保存编码:UTF-8
进⼀步发现
我把两份l分别⽤Google Chrome浏览器打开,结果不⼀样。
encoding=UTF-8 保存编码:GBK 的l:显⽰异常
encoding=UTF-8 保存编码:GBK 的l:正常显⽰
解决思路
让⽂件的encoding编码和保存到磁盘上的编码⼀致。同时思考:为同样的代码在云端和本地运⾏结果不⼀样?
我使⽤dom4j⽣成xml的,我的保存xml的原始代码如下:
原始代码:
/**
* 将document数据写⼊file⽂件中
* @param xmlFile
* @param document
* @throws IOException
*/
private void writeData2Xml(File xmlFile,Document document) throws IOException{
OutputFormat format = atePrettyPrint();
Writer xmlwriter = new FileWriter(xmlFile);
XMLWriter writer = new XMLWriter(xmlwriter,format);
writer.write(document);
writer.close();
xmlwriter.close();
}
查阅资料和验证后
修改代码:
/**
* 将document数据写⼊file⽂件中
* @param xmlFile
* @param document
* @throws IOException
*/
private void writeData2Xml(File xmlFile,Document document) throws IOException{
OutputFormat format = atePrettyPrint();
Writer xmlwriter = new OutputStreamWriter(new FileOutputStream(xmlFile), "UTF-8");
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(xmlwriter,format);
writer.write(document);
writer.close();
xmlwriter.close();
}
解释
Writer xmlwriter = new OutputStreamWriter(new FileOutputStream(xmlFile), "UTF-8");
上⾯代码作⽤是⼀个输出流,将⽂件的内容保存到磁盘上,上⾯的代码通过设置了编码UTF-8,告诉输出流在保存⽂件时使⽤UTF-8编码。⽽之前的代码没有显⽰设置,所以会采⽤系统默认的,说明本地系统和云端不⼀样。
format.setEncoding("UTF-8");
设置xml⽂档开头的中encoding声明,之前代码没有,也就是采⽤默认。
本地没错到云端出错原因
没有显⽰设置编码,⽽是采⽤了系统默认的编码所以出了问题。
查看dom4j相关地⽅的源码后思路
查看源码发现XMLWriter 类的构造有多个其中两个如下,
public XMLWriter(Writer writer, OutputFormat format) {
this.writer = writer;
this.format = format;
namespaceStack.push(Namespace.NO_NAMESPACE);
}使用dom4j解析xml文件
public XMLWriter(OutputStream out, OutputFormat format)
throws UnsupportedEncodingException {
this.format = format;
this.writer = createWriter(out, Encoding());
this.autoFlush = true;
namespaceStack.push(Namespace.NO_NAMESPACE);
}
/**
* Get an OutputStreamWriter, use preferred encoding.
*
* @param outStream
*            DOCUMENT ME!
* @param encoding
*            DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws UnsupportedEncodingException
*            DOCUMENT ME!
*/
protected Writer createWriter(OutputStream outStream, String encoding)
throws UnsupportedEncodingException {
return new BufferedWriter(new OutputStreamWriter(outStream, encoding));
}
发现如果我们⾃⼰不定义Writer的话dom4j会⾃动创建⼀个writer⽽且编码采⽤我们设置的encoding,这样我们为了更好的保证encoding 和保存编码,
代码可以修改如下:
OutputStream out =  new FileOutputStream(xmlFile);
OutputFormat format2 = atePrettyPrint();
format2.setEncoding("UTF-8");//⽂件内容的编码
XMLWriter writer2 = new XMLWriter(out,format2);
writer2.write(document);
writer2.close();
out.close();
encoding和保存⽂件编码的关系(待续…..)
上⾯说:问题是⽂件声明的内容的编码和保存到磁盘上使⽤的编码不⼀致导致读取出来的内容保存到数据库中有中⽂乱码。
解释:encoding的作⽤是声明我的⽂件内容使⽤的是什么编码,注意只是声明,声明是给谁看到?当然是给解析这个xml⽂件的浏览器看的。但是xml⽂档的实际保存编码有可能和ecoding不⼀致,就导致浏览器解析失败。
那我队友解析后出现中⽂乱码怎么回事?和encoding有多⼤关系?
答:和声明的encoding没关系,因为队友⼜不是使⽤浏览器,所以读出内容后并不需要在参考encodng来解析。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。