早期 Java 僅支援位元組流處理二進位檔案,為了處理字元資料,JDK 1.1 引入了以 Reader 和 Writer 為根的字元流體系。本文系統梳理字元流核心類別、編碼轉換機制、緩衝優化策略,並提供完整實戰範例,助你掌握文字檔案讀寫的最佳實踐。
Reader 與 Writer 均為抽象類別,定義了字元流操作的標準契約:
write(char[] cbuf, int off, int len)、flush()、close()read(char[] cbuf, int off, int len)、close()所有具體實作類別(FileReader、BufferedReader 等)必須實作這些方法。
這兩個類別是「位元組流」與「字元流」的轉換樞紐:
InputStreamReader:將位元組輸入流轉換為字元輸入流,構造子可指定字元編碼(預設使用作業系統預設編碼,如中文 Windows 的 GBK/Big5)OutputStreamWriter:將字元輸出流轉換為位元組輸出流,同樣支援編碼指定關鍵洞見:FileReader 實際上繼承自 InputStreamReader,其內部預設使用系統預設編碼,跨平台時易產生亂碼,生產環境強烈建議顯式指定編碼。
FileReader fr = new FileReader("ming.txt");
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
InputStreamReader isr = new InputStreamReader(new FileInputStream("ming.txt"), "UTF-8");
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream("ming.txt"), "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
效能優勢:BufferedReader 內部維護字元緩衝區(預設 8192 字元),大幅減少底層 I/O 系統呼叫次數,readLine() 更適合處理行導向文字資料。
FileWriter fw = new FileWriter("hello.txt");
String s = "hello world";
fw.write(s, 0, s.length());
fw.flush(); // 強制刷新緩衝區
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("hello2.txt"), "UTF-8");
osw.write(s, 0, s.length());
osw.flush();
// 第二個參數 true 表示啟用自動刷新(println/printf/format 後自動 flush)
PrintWriter pw = new PrintWriter(
new OutputStreamWriter(new FileOutputStream("hello3.txt"), "UTF-8"), true);
pw.println(s); // 自動換行並刷新
import java.io.*;
public class TextFileDemo {
public static void main(String[] args) {
String testFile = "ming.txt";
String content = "hello world i like java language";
// 先建立測試檔案
try (PrintWriter pw = new PrintWriter(testFile, "UTF-8")) {
pw.println(content);
} catch (IOException e) {
e.printStackTrace();
}
// 方式1:FileReader 單字元讀取
System.out.println("=== FileReader 讀取 ===");
try (FileReader fr = new FileReader(testFile)) {
int ch;
while ((ch = fr.read()) != -1) System.out.print((char) ch);
} catch (IOException e) { e.printStackTrace(); }
// 方式2:InputStreamReader 指定編碼
System.out.println("\n=== InputStreamReader 讀取 ===");
try (InputStreamReader isr = new InputStreamReader(new FileInputStream(testFile), "UTF-8")) {
int ch;
while ((ch = isr.read()) != -1) System.out.print((char) ch);
} catch (IOException e) { e.printStackTrace(); }
// 方式3:BufferedReader 逐行讀取(推薦)
System.out.println("\n=== BufferedReader 逐行讀取 ===");
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream(testFile), "UTF-8"))) {
String line;
while ((line = br.readLine()) != null) System.out.println(line);
} catch (IOException e) { e.printStackTrace(); }
// 寫入示範
System.out.println("\n=== 寫入操作示範 ===");
try (FileWriter fw = new FileWriter("out1.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("out2.txt"), "UTF-8");
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("out3.txt"), "UTF-8"), true)) {
fw.write(content); fw.flush();
osw.write(content); osw.flush();
pw.println(content); // 自動 flush
} catch (IOException e) { e.printStackTrace(); }
}
}
FileReader/FileWriter 無法指定編碼,僅適合簡單測試readLine() 會捨棄換行符號,寫入時需手動添加 System.lineSeparator() 或 \\nJava 字元流體系透過 InputStreamReader/OutputStreamWriter 解決了位元組與字元的編碼轉換問題,配合緩衝機制提供高效能文字處理能力。掌握編碼指定、緩衝優化、資源管理三大核心要素,即能從容應對各類文字檔案處理場景。