Skip to content

PrintWriter 字符打印流

如果你需要在 Java 中输出格式化的文本内容,PrintWriter 是比 PrintStream 更好的选择。

原因很简单:它支持字符编码。

基本用法

java
// 方式 1:包装 FileWriter(不能指定编码,不推荐)
try (PrintWriter pw = new PrintWriter("output.txt")) {
    pw.println("第一行");
    pw.printf("x = %d%n", 100);
}

// 方式 2:包装 OutputStreamWriter(推荐,可以指定编码)
try (PrintWriter pw = new PrintWriter(
        new OutputStreamWriter(
            new FileOutputStream("output.txt"), StandardCharsets.UTF_8))) {
    pw.println("你好,PrintWriter!");
    pw.printf("姓名: %s, 年龄: %d%n", "张三", 25);
}

// 方式 3:包装 BufferedWriter(更高效)
try (PrintWriter pw = new PrintWriter(
        new BufferedWriter(
            new OutputStreamWriter(
                new FileOutputStream("output.txt"), StandardCharsets.UTF_8)))) {
    pw.println("第一行");
}

和 PrintStream 的对比

对比PrintStreamPrintWriter
底层类型字节流字符流
编码控制不支持(需包装)支持(通过 OutputStreamWriter)
autoFlush 触发println / printf / write + autoFlush=true同左(仅对 OutputStream 包装时有效)
System.outPrintStream
推荐场景二进制数据、调试输出文本文件写入

printf 格式化

java
try (PrintWriter pw = new PrintWriter(
        new OutputStreamWriter(
            new FileOutputStream("output.txt"), StandardCharsets.UTF_8))) {
    // 基本格式化
    pw.printf("整数: %d%n", 42);
    pw.printf("浮点: %.2f%n", 3.14159);
    pw.printf("字符串: %s%n", "Hello");

    // 宽度和对齐
    pw.printf("右对齐: %10s%n", "Hi");
    pw.printf("左对齐: %-10s%n", "Hi");
    pw.printf("补零: %05d%n", 42);

    // 多个参数
    pw.printf("%s = %d, %s = %.2f%n", "age", 25, "height", 1.75);
}

autoFlush

java
// autoFlush = true:对 OutputStream 包装时,println/printf/write 会自动 flush
try (PrintWriter pw = new PrintWriter(
        new BufferedOutputStream(
            new FileOutputStream("log.txt")), true)) {
    pw.println("这条立即刷新");
    pw.printf("格式化: %d%n", 42);
    // 自动 flush,不需要手动调用
}

// autoFlush = false(默认):不自动 flush,需要手动 flush 或 close
try (PrintWriter pw = new PrintWriter(
        new BufferedWriter(
            new OutputStreamWriter(
                new FileOutputStream("log.txt"))))) {
    pw.println("这条不立即刷新");
    pw.flush(); // 手动刷新
    // 或者 close 时自动 flush
}

不抛异常

PrintStream 一样,PrintWriter 不抛 IOException

java
PrintWriter pw = new PrintWriter("output.txt");
pw.println("数据");
if (pw.checkError()) {
    // 检测到错误(磁盘满、IO异常等)
}

写入 HTML 文件

java
try (PrintWriter pw = new PrintWriter(
        new BufferedWriter(
            new OutputStreamWriter(
                new FileOutputStream("page.html"), StandardCharsets.UTF_8)))) {
    pw.println("<!DOCTYPE html>");
    pw.println("<html>");
    pw.println("<head><title>动态页面</title></head>");
    pw.println("<body>");
    pw.println("<h1>用户列表</h1>");
    pw.println("<ul>");
    for (User user : users) {
        pw.printf("<li>%s (%d岁)</li>%n", user.getName(), user.getAge());
    }
    pw.println("</ul>");
    pw.println("</body>");
    pw.println("</html>");
}

常见问题

自动刷新时机

java
// ❌ PrintWriter 包装 Writer 时,autoFlush 不起作用
try (PrintWriter pw = new PrintWriter(
        new BufferedWriter(
            new OutputStreamWriter(
                new FileOutputStream("out.txt"))))) {
    pw.println("不会自动 flush");
    // autoFlush 只对 OutputStream 包装有效,对 Writer 包装无效
}

// ✅ 正确做法:手动 flush
try (PrintWriter pw = new PrintWriter(
        new BufferedWriter(
            new OutputStreamWriter(
                new FileOutputStream("out.txt"))))) {
    pw.println("手动刷新");
    pw.flush();
}

Writer 和 OutputStream 的选择

java
// 如果你需要 autoFlush,包装 OutputStream
try (PrintWriter pw = new PrintWriter(
        new BufferedOutputStream(
            new FileOutputStream("log.txt")), true)) { // true = autoFlush
    pw.println("立即刷新");
}

// 如果你需要指定编码,包装 OutputStreamWriter
try (PrintWriter pw = new PrintWriter(
        new OutputStreamWriter(
            new FileOutputStream("data.txt"), StandardCharsets.UTF_8))) {
    pw.println("UTF-8 编码");
    pw.flush(); // 手动刷新
}

记住这个原则

写文本文件,用 PrintWriter。 永远用 OutputStreamWriter 包装并指定编码。

基于 VitePress 构建