Java中将Document写入OutputStream应使用Transformer序列化:创建TransformerFactory和Transformer,设置输出属性(如编码、缩进、XML声明),用DOMSource和StreamResult包装后调用transform();需确保Transformer编码与OutputStream字节写入一致,避免乱码或异常。
Java中将Document对象(通常来自DOM解析)写入OutputStream,核心是使用Transformer进行序列化。关键在于正确配置Transformer,避免默认输出带XML声明、缩进或编码不一致等问题。
这是最标准、推荐的方式,基于JAXP的XSLT处理器(如Xalan或内置的XSLTC):
TransformerFactory并获取Transformer实例(可设为恒等转换)DOMSource包装Document,用StreamResult包装目标OutputStream
transform()执行序列化示例代码:
TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); // 可选:设置输出属性(如去掉XML声明、指定编码、启用缩进) transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); DOMSource source = new DOMSource(document); StreamResult result = new StreamResult(outputStream); transformer.transform(source, result);
Transformer的ENCODING属性仅控制XML内容中的编码声明(如),实际写入字节流时,OutputStream本身不处理编码——它只写入字节。因此:
outputStream是FileOutputStream,直接写入即可;编码由Transformer负责转换outputStream是ByteArrayOutputStream或网络流,也无需额外包装OutputStream包装成OutputStreamWriter再传给StreamResult——StreamResult只接受原始OutputStream或Writer,混用会导致乱码或异常实际使用中容易遇到几个典型问题:
OutputKeys.ENCODING设为"UTF-8",且XML文档本身节点文本已正确编码(DOM内部以Unicode存储,一般无问题)INDENT,或设OutputKeys.INDENT为"no";也可用transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0")更精确控制Transformer不会输出DOCTYPE;如需保留,需在创建Document时确保DocumentType存在,并确认JDK版本支持(较新版本通常保留)有人尝试先写入StringWriter再转字节,但这是低效且易出错的做法:
string.getBytes("UTF-8") vs Transformer内置编码)OutputStream的灵活性(如写入Socket、Servlet响应)除非特殊限制,应始终优先使用Transformer + StreamResult(OutputStream)路径。