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 免费学习笔记(深入)”;
- 若
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) 路径。