【问题标题】:How does Apache commons IO convert my XML header from UTF-8 to UTF-16?Apache commons IO 如何将我的 XML 标头从 UTF-8 转换为 UTF-16?
【发布时间】:2015-04-17 06:30:41
【问题描述】:

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

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

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

    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);  
}

【问题讨论】:

    标签: java utf-8 apache-commons utf-16 document-conversion


    【解决方案1】:
    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 也有 binary stream support

    【讨论】:

    • 嗨,谢谢。尽管实现了这一点,但我的文档模板的第一行仍然使用“UTF-16”编码标头而不是“UTF-8”标头输出。也许这是我将 Document 对象转换为 String 的方式,我编辑了我的问题以包含它。
    【解决方案2】:

    事实证明,当我将 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-09-19
      • 2010-10-19
      • 2015-09-21
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 1970-01-01
      相关资源
      最近更新 更多