首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java IO 精通:PrintWriter 字元列印輸出流完整解析

     編輯:Java 相關知識

PrintWriter 核心定位

PrintWriter 是字元導向的列印輸出流,繼承自 Writer。它專為格式化文字輸出設計,提供豐富的 print()、println()、printf()、format() 方法,能將各種基本型別與物件自動轉換為字串輸出。與 PrintStream(位元組導向)不同,PrintWriter 直接處理字元,支援指定字元集,適合文字檔案輸出與國際化場景。

建構子多樣性與自動刷新機制

建構子輸出目標自動刷新字元集
PrintWriter(Writer out)字元流false預設
PrintWriter(Writer out, boolean autoFlush)字元流可指定預設
PrintWriter(OutputStream out)位元組流false預設
PrintWriter(OutputStream out, boolean autoFlush)位元組流可指定預設
PrintWriter(String fileName)檔案路徑false預設
PrintWriter(String fileName, String csn)檔案路徑false指定
PrintWriter(File file)File 物件false預設
PrintWriter(File file, String csn)File 物件false指定

自動刷新細節

當 autoFlush=true 時,呼叫 println()、printf()、format() 或寫入換行符會自動觸發 flush()。注意:print() 不會觸發自動刷新,僅 println() 等換行操作會。

核心 API 分類速查

// 格式化輸出
PrintWriter printf(String format, Object... args)
PrintWriter printf(Locale l, String format, Object... args)
PrintWriter format(String format, Object... args)
PrintWriter format(Locale l, String format, Object... args)

// 列印方法(自動轉字串)
void print(boolean b) / print(char c) / print(int i) / print(long l)
void print(float f) / print(double d) / print(char[] s) / print(String s) / print(Object obj)
void println() / println(boolean x) / println(char x) / println(int x) / println(long x)
void println(float x) / println(double x) / println(char[] x) / println(String x) / println(Object x)

// 字元寫入(Writer 基礎方法)
void write(int c) / write(char[] cbuf) / write(char[] cbuf, int off, int len)
void write(String str) / write(String str, int off, int len)

// 追加與檢查
PrintWriter append(char c) / append(CharSequence csq) / append(CharSequence csq, int start, int end)
boolean checkError()  // 檢查是否發生錯誤,不拋出異常
void flush() / void close()

原始碼關鍵機制解析

內部結構

public class PrintWriter extends Writer {
    protected Writer out;           // 底層字元輸出流
    private final boolean autoFlush; // 自動刷新旗標
    private boolean trouble = false; // 錯誤旗標
    private Formatter formatter;     // 格式化器
    private PrintStream psOut = null; // 若包裝 PrintStream,用於錯誤傳播
    private final String lineSeparator; // 系統行分隔符
    // ...
}

錯誤處理策略:吞噬異常、設置旗標

所有寫入方法捕獲 IOException 並設置 trouble = true,不向外拋出。呼叫端需主動呼叫 checkError() 檢查狀態。這設計簡化了列印邏輯,但需開發者養成檢查習慣。

編碼轉換鏈路

建構子接受 OutputStream 時,內部會建立 OutputStreamWriter(指定或預設編碼)再包裝 BufferedWriter,實現位元組到字元的編碼轉換與緩衝。

實戰範例:多種建構方式與格式化輸出

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

public class PrintWriterDemo {
    public static void main(String[] args) {
        demoConstructors();
        demoFormatting();
    }

    // 三種常見建構方式寫入相同內容
    private static void demoConstructors() {
        char[] data = {'a', 'b', 'c', 'd', 'e'};
        
        // 方式 1:包裝 FileOutputStream
        try (PrintWriter pw = new PrintWriter(new FileOutputStream("file1.txt"))) {
            pw.write(data);
        } catch (IOException e) { e.printStackTrace(); }

        // 方式 2:直接指定 File
        try (PrintWriter pw = new PrintWriter(new File("file2.txt"))) {
            pw.write(data);
        } catch (IOException e) { e.printStackTrace(); }

        // 方式 3:指定檔名與 UTF-8 編碼
        try (PrintWriter pw = new PrintWriter("file3.txt", StandardCharsets.UTF_8.name())) {
            pw.write(data);
        } catch (IOException e) { e.printStackTrace(); }
    }

    // 格式化、列印、追加綜合示範
    private static void demoFormatting() {
        try (PrintWriter pw = new PrintWriter("formatted.txt", StandardCharsets.UTF_8.name())) {
            pw.println("=== 格式化輸出示範 ===");
            pw.printf("整數: %d, 十六進位: 0x%X%n", 255, 255);
            pw.printf("浮點: %.2f, 科學記號: %e%n", Math.PI, Math.PI);
            pw.format(Locale.TAIWAN, "本地化數字: %,d%n", 1234567);
            
            pw.print("直接列印: ");
            pw.print(true).print(' ').print(3.14).println(" 結束");
            
            pw.append('[').append("APPEND").append(']').println();
            
            // 錯誤檢查
            if (pw.checkError()) {
                System.err.println("PrintWriter 發生錯誤!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

PrintWriter vs PrintStream 關鍵差異

特性PrintWriterPrintStream
資料單位字元位元組
編碼支援建構子可指定字元集建構子可指定字元集(JDK 1.4+)
自動刷新觸發println/printf/format/換行符println/printf/format/換行符
異常處理吞噬,checkError() 檢查吞噬,checkError() 檢查
適用場景文字檔、報表、日誌、國際化控制台、位元組導向輸出、System.out

最佳實踐建議

  1. 明確指定編碼:生產環境務必使用 PrintWriter(file, StandardCharsets.UTF_8.name()) 避免平台預設編碼差異。
  2. 善用格式化:printf/format 比字串串接效能更好、可讀性更高,支援區域化數字格式。
  3. 定期檢查錯誤:長時間運行的列印任務,定期呼叫 checkError() 並記錄日誌。
  4. 大量輸出考慮緩衝:若包裝未緩衝的 Writer,建議先包裝 BufferedWriter 再傳給 PrintWriter。

PrintWriter 是 Java 文字格式化輸出的利器,掌握其建構選項、自動刷新行為與錯誤處理模式,能讓檔案寫入、報表產生、日誌記錄等工作更加優雅可靠。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved