Skip to content

打印流(PrintWriter)

如果你觉得 BufferedWriter 写文本还不够方便,试试 PrintWriter

它的核心特点:不抛异常,而且 printf() 格式化输出是内置的。

PrintWriter 的特点

  • 不抛异常:写入失败不会抛 IOException,内部维护一个 Writer
  • 自动 flush:当写入换行符或调用 println() 时自动 flush(如果启用了 autoFlush)
  • 格式化输出:支持 printf() 风格的格式化字符串
  • 字符流本质:操作 char 而非 byte,天然适合文本输出

基本用法

java
// 构造方式一:直接指定文件路径
try (PrintWriter pw = new PrintWriter("output.txt")) {
    pw.println("第一行");
    pw.println("第二行");
}

// 构造方式二:指定编码
try (PrintWriter pw = new PrintWriter(
        new OutputStreamWriter(
            new FileOutputStream("output.txt"), StandardCharsets.UTF_8))) {
    pw.println("UTF-8 编码的内容");
}

// 构造方式三:autoFlush 模式(println 时自动 flush)
try (PrintWriter pw = new PrintWriter(
        new FileWriter("output.txt"), true)) { // true = autoFlush
    pw.println("自动 flush"); // 写完立即刷新到磁盘
}

printf 格式化输出

PrintWriter 继承自 Writer,但通过 printf() / format() 支持格式化:

java
try (PrintWriter pw = new PrintWriter(System.out, true)) {
    // %d = 整数, %s = 字符串, %.2f = 两位小数浮点
    pw.printf("用户名: %s, 年龄: %d, 积分: %.2f%n", "张三", 25, 1234.567);
    // 输出:用户名: 张三, 年龄: 25, 积分: 1234.57
}

常用格式化符号

符号说明示例
%d十进制整数%d42
%s字符串%shello
%.2f浮点数,保留 2 位%.2f3.14
%n平台换行符等价于 System.lineSeparator()
%t日期/时间%tF2024-01-15

与 PrintStream 的区别

特性PrintStreamPrintWriter
底层字节流(OutputStream)字符流(Writer)
目标文件、控制台、网络文件、Writer
编码支持字节为单位,无编码可指定字符编码
推荐场景字节数据、日志(System.out文本文件写入(推荐)
java
// ❌ 写文本文件不推荐用 PrintStream
try (PrintStream ps = new PrintStream("output.txt")) {
    ps.println("这是字节流写入");
}

// ✅ 推荐用 PrintWriter 写文本
try (PrintWriter pw = new PrintWriter("output.txt", StandardCharsets.UTF_8)) {
    pw.println("这是字符流写入");
}

自动 flush 的时机

java
// autoFlush = false(默认)
PrintWriter pw = new PrintWriter(new FileWriter("output.txt"));
pw.print("不会自动 flush");  // 可能在缓冲区
pw.close(); // close 时才真正写入

// autoFlush = true
PrintWriter pw = new PrintWriter(new FileWriter("output.txt"), true);
pw.println("写完一行立即 flush"); // println 自动 flush

常见用法:写日志

java
public class Logger {
    private final PrintWriter writer;

    public Logger(String path) throws IOException {
        this.writer = new PrintWriter(
            new BufferedWriter(
                new FileWriter(path, true)), // 追加模式
            true); // autoFlush
    }

    public void info(String msg) {
        writer.printf("%tF %tT [INFO] %s%n",
            new Date(), new Date(), msg);
    }

    public void error(String msg, Throwable t) {
        writer.printf("%tF %tT [ERROR] %s: %s%n",
            new Date(), new Date(), msg, t.getMessage());
    }

    public void close() {
        writer.close();
    }
}

记住这个选择

写文本文件,用 PrintWriter。 写字节数据或调试输出,用 PrintStream

基于 VitePress 构建