一、“中文问题没商量”之Dom4j中的编码问题 
  本文主要讲述的是Dom4j在把Document保存到文件过程中出现的一个中文问题,本文跟《80前》一文一样,以Spring项目无关,请“春迷”们自重、没事勿扰,文中不足之处欢迎大家批评指教。
  Dom4j是一个比较优秀的java开源xml解析项目,支持DOM, SAX and JAXP.,并提供对XPath查询语言的强大支持。因此,在EasyJF团队的很多开源项目中,如EasyJWeb、EasyDBO等都是使用Dom4j来处理xml文件相关操作。
 
1、从一个xml文件中载入一个Dom到内存:
  FileInputStream in = new FileInputStream(new File(fileName));
  SAXReader reader = new SAXReader();
  doc = reader.read(in);
2、把Dom中的数据写入到xml文件中 
  使用Dom4j,要把一个Dom中的数据写入到文件非常简单,API如下:
   public void write(Writer writer) throws IOException;
  因此,假如我们要把一个Document写入到c:\test.xml文件中,可以简单的使用下面的代码即可:
java.io.Writer wr= new java.io.FileWrite(filename);
  doc.write(wr);
 wr.close();//注意,必须要执行close()方法,才会实现真正的写入
  
  这种用法也是Dom4j所推荐我们使用的非常简单的方法。然而,当我们的dom中包含有中文字符数据的时候,这种方法写入的xml文档却无法使直觉打开。会提示类似如下的错误:
   org.dom4j.DocumentException: invalid byte 1 of 1-byte UTF-8 sequence (0xb2) Nested exception: invalid byte 1 of 1-byte UTF-8 sequence (0xb2)
 at org.dom4j.io.SAXReader.read(SAXReader.java:484)
 at org.dom4j.io.SAXReader.read(SAXReader.java:343)
 at

  我们可以看生成的xml文件编码,内容是utf-8的,但文件格式确是ANSI的,如下图所示:

原因分析:
  由于FileWriter默认的输出编码是ANSI编码,而Dom4j中的wirte方法提供的内容实际是以UTF-8保存的,因此造成了包括中文字符的XML文件无法正常阅读。查了半天代码,最后才发现:是UTF字符的问题。当XML中含有中文,而没有指定XML Encoding="UTF-8"的时候,就会产生这样的错误。
 
解决方法:
   不能使用简单的FileWriter,而应该是使用一个能指定具体输出编码的Writer,在JDK的io包中, OutputStreamWriter可以指定输出编码。
  正确的代码如下:
java.io.OutputStream out=new java.io.FileOutputStream(fileName);
  java.io.Writer wr=new java.io.OutputStreamWriter(out,"UTF-8");  
  doc.write(wr);  
  wr.close();
  out.close();
  简化一下可以写成下面的样式:
   java.io.Writer wr=new java.io.OutputStreamWriter(new java.io.FileOutputStream(fileName),"UTF-8");  
  doc.write(wr);  
  wr.close();

小结: 
  由于大多数优秀的基础性开源项目都是老外开发,他们不大可能在中文平台下进行测试,用例数据也很少会使用中文平台,因此,我们即使按照这些开源项目的通用说明文档及用户指南去操作,也会出现很多不可预知的错误。这也是为什么本人要参与组建开源团队EasyJF,提倡搞国产开源,并开发一些基础性的开源框架如EasyJWeb、EasyDBO的一个初衷。
  当然,这里提出的中文问题,算是一个还“没来得及商量”以及要通过一些罕见的处理才能正确运行的中文问题。因此,同样归并到了“中文问题没商量”系列中。

(注:本文作者,EasyJF开源团队 大峡,转载请保留作者声明!)

二、DOM4J中文问题 Invalid byte 1 of 1-byte UTF-8 sequence

http://hlwlemon.blog.sohu.com/81841115.html 本文出处

在用dom4j的时候发现有时会出现这个问题:无法以UTF-8保存xml文件,保存后再次读出的时候会报“Invalid byte 2 of 2-byte UTF-8 sequence.”这样一个错误,检查发现由dom4j生成的这个文件,在使用可正确处理XML编码的任何的编辑器中中文成乱码,从记事本查看并不会出现乱码会正确显示中文。让我很是头痛。。。。
  试着使用GBK、gb2312编码来生成的xml文件却可以正常的被解析。因此怀疑的dom4j没有对utf-8编码进行处理。便开始查看dom4j的原代码。终于发现的问题所在,是自己程序的问题。

在dom4j的范例中新建一个xml文档的代码都类似如下

public void createXML(String fileName) {
  Document doc = org.dom4j.DocumentHelper.createDocument();
  Element root = doc.addElement("book");
  root.addAttribute("name", "我的图书");
  Element childTmp;
  childTmp = root.addElement("price");
  childTmp.setText("21.22");
  Element writer = root.addElement("author");
  writer.setText("李四");
  writer.addAttribute("ID", "001");
  try {
  org.dom4j.io.XMLWriter xmlWriter = new org.dom4j.io.XMLWriter(
  new FileWriter(fileName));
  xmlWriter.write(doc);
  xmlWriter.close();
  }
  catch (Exception e) {
  System.out.println(e);
  }
}

在上面的代码中输出使用的是FileWriter对象进行文件的输出。这就是不能

正确进行文件编码的原因所在,java中由Writer类继承下来的子类没有提供编码

格式处理,所以dom4j也就无法对输出的文件进行正确的格式处理。这时候所保

存的文件会以系统的默认编码对文件进行保存,在中文版的window下java的默认

的编码为GBK,也就是所虽然我们标识了要将xml保存为utf-8格式但实际上文件

是以GBK格式来保存的,所以这也就是为什么能够我们使用GBK、GB2312编码来生

成xml文件能正确的被解析,而以UTF-8格式生成的文件不能被xml解析器所解析

的原因。
  好了现在我们找到了原因所在了,我们来找解决办法吧。首先我们看看dom4j

是如何实现编码处理的
  public XMLWriter(OutputStream out) throws UnsupportedEncodingException {
  //System.out.println("In OutputStream");
  this.format = DEFAULT_FORMAT;
  this.writer = createWriter(out, format.getEncoding());
  this.autoFlush = true;
  namespaceStack.push(Namespace.NO_NAMESPACE);
  }
  public XMLWriter(OutputStream out, OutputFormat format) throws UnsupportedEncodingException {
  //System.out.println("In OutputStream,OutputFormat");
  this.format = format;
  this.writer = createWriter(out, format.getEncoding());
  this.autoFlush = true;
  namespaceStack.push(Namespace.NO_NAMESPACE);

}

protected Writer createWriter(OutputStream outStream, String

encoding) throws UnsupportedEncodingException {
  return new BufferedWriter(
  new OutputStreamWriter( outStream, encoding )
  );
  }

由上面的代码我们可以看出dom4j对编码并没有进行什么很复杂的处理,完全通过java本身的功能来完成。所以我们在使用dom4j的来生成我们的XML文件时不应该直接为在构建XMLWriter时,不应该直接为其赋一个Writer对象,而应该通过一个OutputStream的子类对象来构建。也就是说在我们上面的代码中,不应该用FileWriter对象来构建xml文档,而应该使用FileOutputStream对象来构建,所以将代码修改入下:
  public void createXML(String fileName) {
  Document doc = org.dom4j.DocumentHelper.createDocument();
  Element root = doc.addElement("book");
  root.addAttribute("name", "我的图书");
  Element childTmp;
  childTmp = root.addElement("price");
  childTmp.setText("21.22");
  Element writer = root.addElement("author");
  writer.setText("李四");
  writer.addAttribute("ID", "001");
  try {
  //注意这里的修改

org.dom4j.io.XMLWriter xmlWriter = new org.dom4j.io.XMLWriter(
  new FileOutputStream(fileName));
  xmlWriter.write(doc);
  xmlWriter.close();
  }
  catch (Exception e) {
  System.out.println(e);

}

}

这样生成的代码就是中文的了
异常:Invalid byte 1 of 1-byte UTF-8 sequence.

三、dom4j 中文处理问题编码转换
http://topic.csdn.net/t/20040329/17/2900049.html

正好昨天我遇到这个问题,如此解决:  
  SAXReader reader = new SAXReader();  
  org.dom4j.Document document = reader.read("D:\\ha.xml");  
  OutputFormat of = new OutputFormat();  
  of.setEncoding("gb2312"); //改变编码方式  
  XMLWriter writer = new XMLWriter(new FileWriter "d:\\dom4j.xml"), of);  
   
  List list = document.selectNodes(  
  "//PersonId[@name = 'chen_zhen']");  
  if (list.size() > 0)  
  {  
  org.dom4j.Element e = (org.dom4j.Element)list.get(0);  
  System.out.println(e.toString());  
  e.setAttributue("name", "huo_yuanjia");  
  e.setAttributue("age", "20");  
  e.setName("Fighter"); //改变tag  
  e.setText("0001"); //改变value  
  }  
  writer.write(document);  
  writer.close();
以下函数可以实现编码转换:  
  public void writeXML(String file,Document document,String encoding){  
  try{  
  FileWriter out = new FileWriter(new File(file));  
  OutputFormat format = OutputFormat.createPrettyPrint();  
  format.setEncoding(encoding == null ? format.getEncoding() : encoding);  
  XMLWriter writer = new XMLWriter(out, format);  
  writer.write(document);  
  writer.close();  
  }  
  catch(IOException ex){  
  ex.printStackTrace();  
  }  
  }

四、dom4j 输出UTF-8 XML时中文乱码

http://royboy.javaeye.com/blog/337948
  使用DOM4J的XMLWriter输出UTF-8编码的XML文件时,出现乱码。

首先,设置输出的编码,在这我们使用“utf-8”

Java代码 
OutputFormat format = OutputFormat.createPrettyPrint();  
  format.setEncoding("utf-8");

OutputFormat format = OutputFormat.createPrettyPrint();
  format.setEncoding("utf-8");

输出代码:

Java代码 
try {  
  output = new XMLWriter(new FileWriter("entity.xml"), format);  
  output.write(document);  
  output.close();  
  } catch (IOException e) {  
  e.printStackTrace();  
  }

try {
  output = new XMLWriter(new FileWriter("entity.xml"), format);
  output.write(document);
  output.close();
  } catch (IOException e) {
  e.printStackTrace();
  }
上面的输出如果有中文,可以会出现乱码的问题,将上面的FileWriter改成FileOutputStream便可以了。

Java代码 
try {  
  output = new XMLWriter(new FileOutputStream("entity.xml"), format);  
  output.write(document);  
  output.close();  
  } catch (IOException e) {  
  e.printStackTrace();  
  }

五、dom4j中文指定XML编码为GBK(注:指定为utf-8时仍会出现编码问题,见上面四)

1、文件形式:
  XMLWriter writer = null;

OutputFormat format = OutputFormat.createPrettyPrint();

format.setEncoding("GBK");
try{
  writer= new XMLWriter(new FileWriter(new File("test.xml")),format);//用FileOutputStream更好。
  writer.write(document);

writer.close();  
 }
catch(IOException ioe){ioe.printStackTrace();}

2、String形式,我现在做的框架中,是PO<-->XML--Servlet,不需要生成文件,搜索了半天没搜索出来,后来干脆自己试出来了。
StringWriter sw=new StringWriter();
XMLWriter writer = null;

OutputFormat format = OutputFormat.createPrettyPrint();

format.setEncoding("GBK");
writer=new XMLWriter(format);
 writer.setWriter(sw);
 writer.write(document);
 System.out.println(sw.toString());

最新文章

  1. 【安装Redis】CentOS7 下安装NodeJs+Express+MongoDB+Redis
  2. MVVM架构~mvc,mvp,mvvm大话开篇
  3. GhostDoc Pro v4.9.14093.Cracked.By.SubMain 一款好用的代码注释生成工具——VS插件
  4. BZOJ3058 四叶草魔杖
  5. JSON解析和XML解析
  6. AD9 笔记:
  7. 每天2个android小例子----简单计算器源代码
  8. vSphere文档中心
  9. android签名相关
  10. ubuntu下mysql提示Changed limits: max_open_files:1024解决办法
  11. SaltStack 部署案例 02
  12. 浅谈我的MongoDB学习(一)
  13. hover变化图片
  14. 【转载】Linux Cache Mechanism Summary(undone)
  15. python3 集合set
  16. windows 下安装 docker
  17. php里的二进制安全
  18. 【ActiveMQ】ActiveMQ在CentOS的搭建与使用
  19. 解决easyui jQuery JS的for循环调用ajax异步问题
  20. Cannot evaluate the property expression &quot;$([MSBuild]::ValueOrDefault(&#39;$(VCTargetsPath)&#39;,&#39;$(MSBuildExtensionsPath32)\Microsoft.Cpp\v4.0\V140\&#39;))&quot; found at &quot;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuil

热门文章

  1. 常见排序的Java实现
  2. 吴裕雄--天生自然Numpy库学习笔记:NumPy IO
  3. dojo框架笔记
  4. 关于找不到指定的模块,异常来自HRESULT:0x8007007E的解决方法
  5. 第四节:Vuejs组件及组件之间的交互
  6. Could not find a version that satisfies the requirement win32api (from versions: ) No matching distribution found for win32api
  7. jemter-plugins-maven dependency -WIiki用法配置介绍
  8. Servlet返回的数据js解析问题
  9. 栈结构Stack
  10. Java自学-集合框架 ArrayList和LinkedList的区别