printstream在调用println/printf/format或写入'\n'时自动刷新,printwriter仅在调用这三个方法时刷新;前者刷新字节缓冲区,后者刷新字符缓冲区且支持指定编码。

自动刷新触发条件不同
PrintStream 和 PrintWriter 都支持通过构造参数 autoFlush=true 启用自动刷新,但实际触发时机有明确区别:
- PrintStream:只要调用了 println()、printf()、format(),或写入了换行符(
'\n')就会自动刷新 - PrintWriter:仅在调用 println()、printf() 或 format() 时刷新;写入普通
'\n'字符(比如用write("\n"))不会触发刷新
异常处理策略根本不同
二者对 I/O 异常的响应方式属于设计级差异,直接影响错误排查方式:
- PrintStream:所有输出方法不声明抛出 IOException,发生底层写失败时静默捕获异常,并将内部错误标志置为
true;必须手动调用 checkError() 判断是否出错 - PrintWriter:多数构造方式下也不抛出异常(如传入
File或文件名),但若包装的是带异常声明的Writer(如OutputStreamWriter),则其print/println方法可能抛出 IOException;也可统一用 checkError() 检查
刷新依赖底层流是否真正缓冲
自动刷新不是“强制立即落盘”,而是调用底层流的 flush() 方法。效果取决于被包装的流是否重写了该方法:
- 如果包装的是
FileOutputStream(本身flush()为空操作),即使启用 autoFlush,也不会产生实质刷新效果 - 若包装的是
BufferedOutputStream或OutputStreamWriter(内部含缓冲区),autoFlush 才真正起作用 - 因此,单纯设
autoFlush=true不保证数据实时可见,关键看底层是否具备可刷新的缓冲机制
字符 vs 字节层面的刷新含义
虽然行为表现相似,但二者“刷新”的语义层级不同:
- PrintStream 刷新的是字节缓冲区,输出内容按平台默认编码转成字节后写入,刷新即把这批字节推送到底层
- PrintWriter 刷新的是字符缓冲区,它先缓存字符,再由编码器(如 UTF-8 编码器)分批转为字节;刷新意味着字符缓冲清空并触发编码写入
- 这意味着:PrintWriter 在指定编码(如
"UTF-8")时,能更可控地避免乱码;PrintStream 的编码不可控,容易因平台差异导致意外











