在Java中将DOM Document转换为ByteArrayOutputStream时的字符编码问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Java中将DOM Document转换为ByteArrayOutputStream时的字符编码问题相关的知识,希望对你有一定的参考价值。

由于从DOM Document转换为ByteArrayOutputStream,我得到了特殊字符。 Document对象在内容方面很好,我的意思是,标签的拉丁字符内容(即“ç”,“ú”,“Ú”,“ã”等)是正确的。然而,转换为ByteArrayOutputStream导致奇怪的特征。例如,拉丁字符“Ú”表示为“Ô(两个字节)。显然,这是一个与编码转换相关的问题,但我不希望在这一点上得到这个。从DOM Document到ByteArrayOutputStream的转换通过以下方法执行:

private String write(final Document doc) throws TransformerException {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer trans = tf.newTransformer();

    trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");        
    trans.transform(new DOMSource(doc), new StreamResult(os)); //Here is the problem

    String xmlData = os.toString(); //The conversion error is passed on

    return xmlData;
}

我对这个问题有更多细节。当应用程序在Linux / UNIX上运行时,这种方法非常相似。当应用程序在Windows OS系列上运行时,转换根本不起作用。然而,当我调试这个方法时,我注意到“os”对象的内容已经包含了字符“Ú”的错误表示,这导致我在trans.transform执行期间出现问题。

有人可以帮我解决这个问题吗?我该怎么做才能避免这种编码问题?

提前感谢您的帮助。此致,安德森

更新:嗨Makaveli84!这是结果。根据您的建议,我已对代码进行了更改,确保编码为“ISO-8859-1”。这解决了特殊字符问题;但是,XML声明已从更改

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

<?xml version="1.0" encoding="ISO-8859-1"?>

这是有道理的,但业务案例限制了XML声明

话虽如此,我决定做的是通过设置这样做来摆脱XML声明

trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")

之后,我刚刚通过串联添加了字符串<?xml version="1.0" encoding="UTF-8"?>,如下所示:

xmlData = "<?xml version="1.0" encoding="UTF-8"?>".concat(os.toString());

这是我发现在转换为String期间将XML中的拉丁字符保留在XML中的方法,我的意思是,这是我拙见的解决方法。

显然,这不是解决此处发布的原始问题的优雅方法。然后我的问题是:有没有办法通过不使用上述解决方案来实现我的目标?

以下是调整后的完整方法:

private String write(final Document doc) throws TransformerException {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer trans = tf.newTransformer();

    trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    trans.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
    trans.transform(new DOMSource(doc), new StreamResult(os));

    String xmlData = null;

    xmlData = "<?xml version="1.0" encoding="UTF-8"?>".concat(os.toString());

    return xmlData;
}

关于冒烟测试的结果:我在Windows上测试了新方法,现在问题已得到解决。另一方面,在Linux上代码产生特殊字符,我的意思是,Linux上的拉丁字符变成了歪曲(即'Ó'在XML中变为'¿')。

我应该测试哪个操作系统正在运行该应用程序才能正确处理拉丁字符?

欢迎任何建议......

答案

通过使用单字节映射字符集(如ISO-8859-1)解码(转换)为字节数组,可以解决一半问题。

改变这个

trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

对此

trans.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");

但是,从byte-array到String时没有任何转义。您需要检测原始编码并在转换字节数组toString时使用该信息。例如:

String xmlData = os.toString("UTF-8");

要么

String xmlData = os.toString("UTF-16");

以上是关于在Java中将DOM Document转换为ByteArrayOutputStream时的字符编码问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中将 org.bson.Document 转换为 org.bson.BasicBSONObject?

如何将 org.w3c.dom.Document 对象转换为字符串?

Java+DOM:如何将没有命名空间的 DOM 树转换为可感知命名空间的 DOM 树?

在 vuejs 中将字符串转换为 Dom

如何在 java 中将 org.w3c.dom.Element 输出为字符串格式?

java 中 byte[]FileInputStream 互相转换