代码之家  ›  专栏  ›  技术社区  ›  Mike Tunnicliffe

使用Java和UTF-8编码生成有效的XML

  •  19
  • Mike Tunnicliffe  · 技术社区  · 16 年前

    我正在使用JAXP生成和解析一个XML文档,从中从数据库加载一些字段。

    序列化XML的代码:

    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document doc = builder.newDocument();
    Element root = doc.createElement("test");
    root.setAttribute("version", text);
    doc.appendChild(root);
    
    DOMSource domSource = new DOMSource(doc);
    TransformerFactory tFactory = TransformerFactory.newInstance();
    
    FileWriter out = new FileWriter("test.xml");
    Transformer transformer = tFactory.newTransformer();
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.transform(domSource, new StreamResult(out)); 
    

    解析XML的代码:

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse("test.xml");
    

    我遇到了以下例外情况:

    [Fatal Error] test.xml:1:4: Invalid byte 1 of 1-byte UTF-8 sequence.
    Exception in thread "main" org.xml.sax.SAXParseException: Invalid byte 1 of 1-byte UTF-8 sequence.
        at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
        at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
        at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
        at com.test.Test.xml(Test.java:27)
        at com.test.Test.main(Test.java:55)
    

    字符串文本包括u-umlaut和o-umlaut(字符代码0xFC和0xF6)。这些是导致错误的字符。当我自己逃脱字符串以使用ü和ö那么问题就消失了。当我写出XML时,其他实体会自动编码。

    如何在不替换这些字符的情况下正确写入/读取我的输出?

    (我已经阅读了以下问题:

    How to encode characters from Oracle to XML?

    Repairing wrong encoding in XML files )

    2 回复  |  直到 8 年前
        1
  •  31
  •   kdgregory    16 年前

    使用FileOutputStream而不是FileWriter。

    后者应用自己的编码,几乎可以肯定不是UTF-8(根据您的平台,它可能是Windows-1252或is-8859-1)。

    编辑(现在我有时间了):

    不带序言的XML文档可以编码为UTF-8或UTF-16。使用序言,可以指定其编码(序言只能包含US-ASCII字符,因此序言始终可读)。

    读者处理人物;它将解码底层InputStream的字节流。因此,当您将Reader传递给解析器时,您告诉它您已经处理了编码,因此解析器将忽略序言。当你传递一个InputStream(读取字节)时,它不会做出这种假设,而是会查看序言来定义编码——如果没有,则默认为UTF-8/UTF-16。

    我从未尝试读取用UTF-16编码的文件。我怀疑解析器将查找字节顺序标记(BOM)作为文件的前2个字节。

        2
  •  5
  •   Igor Popov    11 年前

    当然 0xFC 0xF6 无效 UTF-8 字符。这些应该被细化为两个字节序列: 0x3CBC 0x3CB6 .

    最有可能的问题是字符的原始来源被定义为 UTF-8 当他们不是。