transformer.setOutputProperty(OutputKeys.ENCODING,“UTF-8”)不起作用

我有以下方法将XMLDom写入流:

public void writeToOutputStream(Document fDoc, OutputStream out) throws Exception { fDoc.setXmlStandalone(true); DOMSource docSource = new DOMSource(fDoc); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "no"); transformer.transform(docSource, new StreamResult(out)); } 

我正在测试其他一些XMLfunction,这只是我用来写入文件的方法。 我的测试程序生成了33个测试用例,其中写出了文件。 其中28个具有以下标题:

 ... 

但出于某种原因,现在有一个测试用例产生:

 ... 

还有四种产品:

 ... 

您可以清楚地看到,我将ENCODING输出键设置为UTF-8。 这些测试曾用于早期版本的Java。 我没有在一段时间内(超过一年)运行测试,但今天在“Java(TM)SE运行时环境(版本1.6.0_22-b04)”上运行我得到了这个有趣的行为。

我已经validation导致问题的文档是从最初具有这些编码的文件中读取的。 似乎新版本的库试图保留已读取的源文件的编码。 但这不是我想要的……我真的希望输出是UTF-8。

有没有人知道可能导致变压器忽略UTF-8编码设置的任何其他因素? 还有什么必须在文档上设置,以忘记最初读取的文件的编码?

更新:

我在另一台机器上检查了同一个项目,在那里构建并运行了测试。 在那台机器上,所有测试都通过了! 所有文件的标题中都有“UTF-8”。 该机器具有“Java(TM)SE运行时环境(版本1.6.0_29-b11)”两台机器都运行Windows 7.在新机器上运行正常,jdk1.5.0_11用于进行构建,但是在旧机器上运行机器jdk1.6.0_26用于构建。 用于两个版本的库完全相同。 在构建时是否可以与1.5的JDK 1.6不兼容?

更新:

4。5年后,Java库仍然被打破,但由于Vyrx的建议,我终于有了一个合适的解决方案!

 public void writeToOutputStream(Document fDoc, OutputStream out) throws Exception { fDoc.setXmlStandalone(true); DOMSource docSource = new DOMSource(fDoc); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "no"); out.write("".getBytes("UTF-8")); transformer.transform(docSource, new StreamResult(out)); } 

解决方案是禁用标头的写入,并在将XML序列化为输出流之前写入正确的标头。 Lame,但它会产生正确的结果。 4年前破裂的测试现在再次开始!

在序列化表情符号时,我在Android上遇到了同样的问题。 在变换器中使用UTF-8编码时,输出是HTML字符实体(UTF-16代理对),这将随后破坏读取数据的其他解析器。

这就是我最终解决它的方法:

 StringWriter sw = new StringWriter(); sw.write(""); Transformer t = TransformerFactory.newInstance().newTransformer(); // this will work because we are creating a Java string, not writing to an output t.setOutputProperty(OutputKeys.ENCODING, "UTF-16"); t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); t.transform(new DOMSource(elementNode), new StreamResult(sw)); return IOUtils.toInputStream(sw.toString(), Charset.forName("UTF-8")); 

回答以下代码的问题对我有用。 这可以采用输入编码并将数据转换为输出编码。

  ByteArrayInputStream inStreamXMLElement = new ByteArrayInputStream(strXMLElement.getBytes(input_encoding)); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document docRepeat = db.parse(new InputSource(new InputStreamReader(inStreamXMLElement, input_encoding))); Node elementNode = docRepeat.getElementsByTagName(strRepeat).item(0); TransformerFactory tFactory = null; Transformer transformer = null; DOMSource domSourceRepeat = new DOMSource(elementNode); tFactory = TransformerFactory.newInstance(); transformer = tFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.ENCODING, output_encoding); ByteArrayOutputStream bos = new ByteArrayOutputStream(); StreamResult sr = new StreamResult(new OutputStreamWriter(bos, output_encoding)); transformer.transform(domSourceRepeat, sr); byte[] outputBytes = bos.toByteArray(); strRepeatString = new String(outputBytes, output_encoding); 

我花了大量时间来调试这个问题,因为它在我的机器上运行良好(Ubuntu 14 + Java 1.8.0_45)但在生产中运行不正常(Alpine Linux + Java 1.7)。

与我的期望相反,上面提到的答案没有帮助。

 ByteArrayOutputStream bos = new ByteArrayOutputStream(); StreamResult sr = new StreamResult(new OutputStreamWriter(bos, "UTF-8")); 

但这个按预期工作

 val out = new StringWriter() val result = new StreamResult(out) 

关于什么?:

 public static String documentToString(Document doc) throws Exception{ return(documentToString(doc,"UTF-8")); }// public static String documentToString(Document doc, String encoding) throws Exception{ TransformerFactory transformerFactory =TransformerFactory.newInstance(); Transformer transformer = null; if ( "".equals(validateNullString(encoding) ) ) encoding = "UTF-8"; try{ transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes") ; transformer.setOutputProperty(OutputKeys.ENCODING, encoding) ; }catch (javax.xml.transform.TransformerConfigurationException error){ return null; } Source source = new DOMSource(doc); StringWriter writer = new StringWriter(); Result result = new StreamResult(writer); try{ transformer.transform(source,result); }catch (javax.xml.transform.TransformerException error){ return null; } return writer.toString(); }//documentToString 

我可以通过包装传递给DOMSource构造函数的Document对象来解决这个问题。 我的包装器的getXmlEncoding方法总是返回null,所有其他方法都被委托给包装的Document对象。

我在这里拍摄了一个疯狂的镜头,但是你提到你正在读取测试数据的文件。 您是否可以确保使用正确的编码读取文件,因此当您写入OutputStream时,您已经拥有正确编码的数据?

所以有一些像新的InputStreamReader(新的FileInputStream(fileDir),“UTF8”)。

不要忘记FileReader的单参数构造函数始终使用平台默认编码: 此类的构造函数假定默认字符编码和默认字节缓冲区大小是合适的。

尝试专门在StreamResult上设置编码:

 StreamResult result = new StreamResult(new OutputStreamWriter(out, "UTF-8")); 

这样,它应该只能用UTF-8写出来。