在 Java I/O 體系中,字元輸出流 Writer 與字元輸入流 Reader 互為對應,兩者在設計模式與類別結構上高度相似。本文將系統梳理 Writer 及其核心子類的用途、結構關係與實戰範例,幫助開發者快速掌握字元輸出的最佳實踐。
每個字元輸出流類別都針對特定場景設計,主要分類如下:
OutputStream。FileOutputStream。char[]) 作為緩衝區,支援動態擴容,適合記憶體內字串構建。PipedReader 實現同一 JVM 內執行緒間的管道通訊。StringBuffer,適合高效拼裝字串。Writer 增加緩衝區,減少實際 I/O 呼叫,提升效能;新增 newLine() 等實用方法。printf、println 等便利方法,且不拋出受檢異常。下圖展示 Writer 及 Reader 的繼承與裝飾關係(含核心子類):

OutputStreamWriter 的每個建構子都要求傳入一個 OutputStream,底層委派給 StreamDecoder 處理字元編碼。典型用法是包裝標準輸出或網路/檔案位元組流:
Writer writer = new OutputStreamWriter(System.out, StandardCharsets.UTF_8);
writer.write("Hello, World!");
writer.flush(); // 確保緩衝資料送達底層流
writer.close();
關鍵點:指定 Charset 避免平台預設編碼導致亂碼;flush() 僅刷新字元緩衝,close() 會關閉底層位元組流。
FileWriter 繼承 OutputStreamWriter,建構子內部自動建立 FileOutputStream。適用於直接寫入文字檔:
try (Writer writer = new FileWriter("C:\\data\\output.txt", StandardCharsets.UTF_8)) {
writer.write('A');
writer.write("中文測試\n");
writer.flush();
}
注意:JDK 11+ 建構子支援直接指定 Charset;舊版本需自行包裝 OutputStreamWriter。
內部維護可擴容的 char[],適合「先寫入記憶體,再一次性取出」的場景:
CharArrayWriter writer = new CharArrayWriter(1024);
writer.write("動態擴容測試");
char[] result = writer.toCharArray(); // 取得最終字元陣列
String str = writer.toString(); // 直接轉字串
必須配對使用,PipedWriter 連接 PipedReader(或反向),實現生產者-消費者模型。讀寫雙方均會阻塞,直到資料可用或緩衝區有空間:
PipedWriter pw = new PipedWriter();
PipedReader pr = new PipedReader(pw);
// 執行緒 A 寫入
new Thread(() -> {
try { pw.write("訊息內容"); pw.close(); } catch (IOException e) { e.printStackTrace(); }
}).start();
// 執行緒 B 讀取
new Thread(() -> {
try { char[] buf = new char[1024]; int len = pr.read(buf); System.out.println(new String(buf, 0, len)); }
catch (IOException e) { e.printStackTrace(); }
}).start();
為任意 Writer 增加緩衝區(預設 8KB,可自訂大小),大幅減少系統呼叫:
try (BufferedWriter bw = new BufferedWriter(
new FileWriter("log.txt", StandardCharsets.UTF_8), 16 * 1024)) {
bw.write("第一行");
bw.newLine(); // 跨平台換行
bw.write("第二行");
}
內部委派 StringBuffer,提供 Writer 介面,方便 API 互通:
StringWriter sw = new StringWriter();
sw.write("Hello ");
sw.write("World");
String result = sw.toString(); // "Hello World"
支援 printf、format、println 等豐富方法,且吞噬受檢異常(需透過 checkError() 檢查):
PrintWriter pw = new PrintWriter(System.out, true, StandardCharsets.UTF_8); // autoFlush=true
pw.printf("編號: %05d, 價格: %.2f%n", 101, 99.9);
pw.println("自動換行並刷新");
FileWriter(path, charset) 或手動包裝 OutputStreamWriter。BufferedWriter 是效能提升的最低成本手段。flush() 僅推送字元緩衝;close() 會關閉底層位元組流,後續不可再寫入。PipedWriter/Reader 僅適用於同一 JVM 內執行緒,跨進程請用 Socket 或檔案。Writer 體系;處理二進位資料(圖片、影音、序列化位元組)用 OutputStream 體系。兩者可透過 OutputStreamWriter/InputStreamReader 互轉。checkError() 檢查即可。