OutputStreamWriter 通过委托 StreamEncoder 实现字符到字节的编码转换,其自身仅负责封装与调度;构造时根据 Charset 或编码名创建 StreamEncoder,后者利用 CharsetEncoder、ByteBuffer 和 OutputStream 完成实际编码与输出。
OutputStreamWriter 本身不直接操作 StreamEncoder,而是通过内部委托给它完成编码转换。Java 的字符流到字节流转换,核心编码逻辑实际由 StreamEncoder 承担,OutputStreamWriter 主要负责封装和调度。
OutputStreamWriter 在构造时(例如传入 Charset 或编码名),会创建一个 StreamEncoder 实例,并将后续的 write() 调用转发给它。这个过程对用户透明——你调用的是字符写入方法,底层自动触发编码器将 char 数组按指定 Charset 转为 byte 序列,再写入底层 OutputStream。
OutputStreamWriter 使用系统默认 Charset 构造 StreamEncoder
Charset 对象(如 StandardCharsets.UTF_8),则基于该 Charset 初始化 StreamEncoder
"GBK"),会先查表获取对应 Charset,再构建 StreamEncoder
StreamEncoder 是 JDK 内部类(sun.nio.cs.StreamEncoder),负责真正的字符→字节转换。它持有:
CharsetEncoder(来自指定 Charset),用于执行编码逻辑ByteBuffer 缓冲区,暂存编码后的字节OutputStream,最终把字节刷出每次 write() 时,StreamEncoder 将输入的 char 数据送入 CharsetEncoder,处理替换、错误策略(如 MalformedInputAction.REPLACE),生成字节并缓存;flush() 或缓冲区满时,才调用 out.write() 输出。
立即学习“Java免费学习笔记(深入)”;
开发者无法直接 new StreamEncoder(它是 package-private 类),但可通过以下方式控制其行为:
CharsetEncoder 的编码规则和容错策略Charset.newEncoder().onMalformedInput(...).onUnmappableCharacter(...) 构建自定义 encoder,再包装成 Charset 传入 OutputStreamWriter
flush() 强制清空 StreamEncoder 的内部缓冲区当你执行:
Writer w = new OutputStreamWriter(new FileOutputStream("a.txt"), StandardCharsets.UTF_8);<br>w.write("你好");<br>w.flush();
实际发生的是:
OutputStreamWriter 创建 UTF-8 对应的 StreamEncoder
write("你好") → StreamEncoder 将两个汉字转为 6 字节 UTF-8 编码(E4 BD A0 E5 A5 BD)flush() → StreamEncoder 把这 6 字节写入 FileOutputStream