1

我正在使用 Java 6。我有一个 XML 模板,它的开头是这样的

<?xml version="1.0" encoding="UTF-8"?>

但是,我注意到当我使用以下代码(使用 Apache Commons-io 2.4)解析和输出它时……</p>

    Document doc = null;
    InputStream in = this.getClass().getClassLoader().getResourceAsStream(“my-template.xml”);

    try
    {
        byte[] data = org.apache.commons.io.IOUtils.toByteArray( in );
        InputSource src = new InputSource(new StringReader(new String(data)));

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        doc = builder.parse(src);
    }
    finally
    {
        in.close();
    }

第一行输出为

<?xml version="1.0" encoding="UTF-16”?>

解析/输出文件时我需要做什么才能使标头编码保持“UTF-8”?

编辑:根据给出的建议,我将代码更改为

    Document doc = null;
    InputStream in = this.getClass().getClassLoader().getResourceAsStream(name);

    try
    {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        doc = builder.parse(in);
    }
    finally
    {
        in.close();
    }

但是尽管我的输入元素模板文件的第一行是

<?xml version="1.0" encoding="UTF-8"?>

当我将文档输出为它产生的字符串时

<?xml version="1.0" encoding="UTF-16"?>

作为第一行。这是我用来将“doc”对象输出为字符串的方法...

private String getDocumentString(Document doc)
{
    DOMImplementationLS domImplementation = (DOMImplementationLS)doc.getImplementation();
    LSSerializer lsSerializer = domImplementation.createLSSerializer();
    return lsSerializer.writeToString(doc);  
}
4

2 回答 2

2
new StringReader(new String(data))

这是错误的。您应该让解析器使用(例如)DocumentBuilder.parse(InputStream)检测文档编码:

doc = builder.parse(in);

将 DOM 序列化为何种编码取决于您如何编写它。内存中的 DOM 没有编码的概念。

将文档写入带有 UTF-8 声明的字符串:

import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.ls.*;

public class DomIO {
    public static void main(String[] args) throws Exception {
        Document doc = DocumentBuilderFactory.newInstance()
                                             .newDocumentBuilder()
                                             .newDocument();
        doc.appendChild(doc.createElement("foo"));
        System.out.println(getDocumentString(doc));
    }

    public static String getDocumentString(Document doc) {
        DOMImplementationLS domImplementation = (DOMImplementationLS) 
                                                 doc.getImplementation();
        LSSerializer lsSerializer = domImplementation.createLSSerializer();
        LSOutput lsOut = domImplementation.createLSOutput();
        lsOut.setEncoding("UTF-8");
        lsOut.setCharacterStream(new StringWriter());
        lsSerializer.write(doc, lsOut);
        return lsOut.getCharacterStream().toString();
    }
}

如果您希望序列化程序在输出时正确编码文档,则LSOutput支持二进制流。

于 2015-02-16T17:10:01.677 回答
0

事实证明,当我将 Document -> String 方法更改为

private String getDocumentString(Document doc)
{
    String ret = null;
    DOMSource domSource = new DOMSource(doc);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer;
    try
    {
        transformer = tf.newTransformer();
        transformer.transform(domSource, result);
        ret = writer.toString();
    }
    catch (TransformerConfigurationException e)
    {
        e.printStackTrace();
    }
    catch (TransformerException e)
    {
        e.printStackTrace();
    }
    return ret;
}

'encoding="UTF-8"' 标头不再输出为 'encoding="UTF-16"'。

于 2015-02-17T19:24:27.727 回答