printstream是字节流,不支持显式指定编码,默认用系统编码,异常被静默处理;printwriter是字符流,需通过outputstreamwriter或files.newbufferedwriter指定编码,可抛出ioexception,推荐用于需编码控制的文本输出。

在 Java 中,PrintStream 和 PrintWriter 都是用来方便地输出文本的类,它们都提供了 print()、println()、printf() 等易用方法。但它们的定位和适用场景略有不同:前者更偏向底层字节流(默认使用平台默认编码),后者是字符流(可显式指定编码,推荐用于文本输出)。
PrintStream:适合简单输出到控制台或文件(注意编码限制)
PrintStream 是 OutputStream 的子类,本质是字节流。它内部会将字符转为字节,默认使用系统默认编码(如 Windows 上可能是 GBK),**不支持显式指定字符编码**——这是它用于文本输出时的主要隐患。
常见用法:
- 重定向
System.out:例如System.setOut(new PrintStream("output.txt")),之后所有System.out.println()都写入文件; - 直接构造写文件:
new PrintStream(new FileOutputStream("log.txt")); - 支持自动刷新(传
true第二个参数),但仅对println()、printf()、format()生效,print()不触发; - 不会抛出
IOException(异常被静默吞掉),只通过checkError()检测,容易掩盖问题。
PrintWriter:推荐用于文本输出(支持编码、异常可控)
PrintWriter 是 Writer 的子类,属于字符流,**可以明确指定字符编码**(需配合 OutputStreamWriter),也支持自动刷新,且能正常抛出 IOException(构造时可选是否忽略异常)。
正确创建带编码的 PrintWriter:
PrintWriter writer = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream("data.txt"), "UTF-8"
), true // 自动刷新
);
或者用 Java 7+ 的 NIO 方式更简洁:
PrintWriter writer = new PrintWriter(Files.newBufferedWriter(
Paths.get("data.txt"), StandardCharsets.UTF_8), true);
关键点:
- 必须通过
OutputStreamWriter或Files.newBufferedWriter()指定编码,否则默认使用平台编码; - 自动刷新只对
println()、printf()、format()有效; - 记得调用
close()或flush(),否则缓冲区内容可能未写出; - 构造时若传
false(不自动刷新),需手动flush()才能确保内容落盘。
PrintStream vs PrintWriter:怎么选?
简单判断依据:
- 输出到控制台(
System.out)、或写日志且不关心编码细节 →PrintStream足够轻便; - 写文件、网络响应、需要保证 UTF-8 等特定编码、或要求异常可捕获 → 用
PrintWriter(务必包装好编码); - 避免直接用
PrintWriter(File)构造器——它不支持指定编码,等同于用平台默认编码,跨平台易出乱码; - 如果要格式化输出(如 JSON、CSV、HTML),两者都支持
printf(),但PrintWriter更安全可控。
一个小提醒:别忘了关闭资源
无论用哪个类,只要关联了文件或网络通道,就该及时释放。推荐用 try-with-resources:
try (PrintWriter out = new PrintWriter(
Files.newBufferedWriter(Paths.get("note.txt"), StandardCharsets.UTF_8))) {
out.println("Hello, 世界");
out.printf("数值:%d,浮点:%f%n", 42, 3.1415);
} // 自动 close()
这样既简洁又不会遗漏清理。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











