【问题标题】:Producing valid XML with Java and UTF-8 encoding使用 Java 和 UTF-8 编码生成有效的 XML
【发布时间】:2010-10-01 09:27:43
【问题描述】:

我正在使用 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)

【问题讨论】:

    标签: java xml encoding utf-8


    【解决方案1】:

    使用 FileOutputStream 而不是 FileWriter。

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

    编辑(现在我有时间):

    允许将没有序言的 XML 文档编码为 UTF-8 或 UTF-16。序言允许指定其编码(序言只能包含 US-ASCII 字符,因此序言始终可读)。

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

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

    【讨论】:

    • 很好很简单,我确实想过改成这个,但放弃了这个想法,因为我没有看到在构造函数中指定编码的方法。效果很好,谢谢。
    • 很好的答案——从现在开始我会一直在 FileWriter 中寻找隐藏的陷阱!
    • 我不想使用文件。我的信息来自数据库。我构建 dom 并将其传递给 Xades 库。
    【解决方案2】:

    好吧,当然0xFC0xF6 不是有效的UTF-8 字符。这些应该被限定为两个字节序列:0x3CBC0x3CB6

    问题很可能是字符的原始来源被定义为UTF-8,而实际上并非如此。

    【讨论】:

    • 将 FileWriter 更改为 FileOutputStream 确实导致这些字符被编码为两个字节序列:0xC3BC 和 0xC3B6。
    猜你喜欢
    • 2011-11-28
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 2012-11-07
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多