Java中将Document写入OutputStream应使用Transformer序列化:创建TransformerFactory和Transformer,设置输出属性(如编码、缩进、XML声明),用DOMSource和StreamResult包装后调用transform();需确保Transformer编码与OutputStream字节写入一致,避免乱码或异常。

Java中将Document对象(通常来自DOM解析)写入OutputStream,核心是使用Transformer进行序列化。关键在于正确配置Transformer,避免默认输出带XML声明、缩进或编码不一致等问题。
使用Transformer将Document写入OutputStream
这是最标准、推荐的方式,基于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);
注意OutputStream的编码与Transformer编码需一致
Transformer的ENCODING属性仅控制XML内容中的编码声明(如),实际写入字节流时,OutputStream本身不处理编码——它只写入字节。因此:
立即学习“Java免费学习笔记(深入)”;
这本书给出了一份关于python这门优美语言的精要的参考。作者通过一个完整而清晰的入门指引将你带入python的乐园,随后在语法、类型和对象、运算符与表达式、控制流函数与函数编程、类及面向对象编程、模块和包、输入输出、执行环境等多方面给出了详尽的讲解。如果你想加入 python的世界,David M beazley的这本书可不要错过哦。 (封面是最新英文版的,中文版貌似只译到第二版)
- 若
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")更精确控制 -
DOCTYPE丢失:默认
Transformer不会输出DOCTYPE;如需保留,需在创建Document时确保DocumentType存在,并确认JDK版本支持(较新版本通常保留)
替代方案:使用javax.xml.parsers.DocumentBuilder + StringWriter(不推荐)
有人尝试先写入StringWriter再转字节,但这是低效且易出错的做法:
- 会把整个XML加载为字符串,内存开销大
- 手动转字节时易忽略编码一致性(如
string.getBytes("UTF-8")vsTransformer内置编码) - 无法流式处理,丧失
OutputStream的灵活性(如写入Socket、Servlet响应)
除非特殊限制,应始终优先使用Transformer + StreamResult(OutputStream)路径。









