PrintStream是字节流,依赖平台编码易乱码,适合控制台输出;PrintWriter是字符流,支持显式指定UTF-8等编码,更适合文本文件处理与国际化场景。

PrintStream 和 PrintWriter 都能方便地打印格式化文本,关键在选对类、配好参数、用对方法。不需要手写字符串拼接或手动编码转换,靠 printf、println 和自动刷新机制就能搞定。
PrintStream:适合快速写文件或兼容 System.out 场景
它是字节流,底层依赖编码转换,所以必须显式指定字符集,否则中文容易变问号。构造时用 FileOutputStream 包装文件,再传入 UTF-8 编码和自动刷新开关:
- 正确写法:
new PrintStream(new FileOutputStream("log.txt"), true, StandardCharsets.UTF_8) -
true表示开启 auto-flush,这样每次println()或printf(...%n)后内容立刻写入文件 -
printf支持完整格式化语法,比如ps.printf("用户 %s 登录时间:%tF%n", name, System.currentTimeMillis()) - 注意:
print()不触发刷新,只用它会卡在缓冲区;必须搭配println()、%n或手动flush()
PrintWriter:更适合纯文本输出和日志记录
它是字符流,构造更直接,支持字符串路径 + 编码,语义清晰,乱码风险更低:
- 推荐写法:
new PrintWriter("log.txt", "UTF-8")(Java 10+)或new PrintWriter(new OutputStreamWriter(new FileOutputStream("log.txt"), StandardCharsets.UTF_8)) - 自动刷新需显式开启:
new PrintWriter(out, true),否则printf()写完也不会落盘 - 支持
append()连续写、format()多参数格式化,行为与printf一致 - 出错不抛异常,但可用
checkError()主动检测——适合不想被异常打断的日志场景
避免常见坑的实操要点
不管用哪个类,这几个细节一错就“看着没输出”或“全是乱码”:
立即学习“Java免费学习笔记(深入)”;
- 别用
PrintStream(String)构造器写文件——它已被弃用,仅用于内部(如 System.out),不是文件接口 - 写完必须
close(),或用try-with-resources,否则缓冲区数据可能丢失 - 换行统一用
%n,它自动适配系统(Windows 是\r\n,Linux/macOS 是\n),不用硬写\n或\r\n - IDE 查看日志文件前,确认文件编码设置为 UTF-8,否则即使写对了也显示为方块或问号
简单对比:什么时候该选谁
不必死记区别,看用途选:
- 要重定向
System.out到文件?用PrintStream,它和System.out是同类 - 写日志、配置、报表等纯文本?优先
PrintWriter,编码可控、API 更干净 - 需要和网络响应头、二进制混合输出?只能用
PrintStream,因为它是字节流 - 项目已用 JDK 7+,且只是写文本文件?考虑
Files.newBufferedWriter(Paths.get("x.txt"), UTF_8),更现代、自动关流、无需包装



















