FileReader 與 FileWriter 是 Java 針對字元檔案操作提供的便利類別,分別繼承自 InputStreamReader 與 OutputStreamWriter。它們內部封裝了 FileInputStream/FileOutputStream,預設使用平台預設字元集(Charset.defaultCharset())進行位元組與字元轉換,適合簡單文字檔案讀寫。
public class FileReader extends InputStreamReader {
public FileReader(String fileName) throws FileNotFoundException {
super(new FileInputStream(fileName));
}
public FileReader(File file) throws FileNotFoundException {
super(new FileInputStream(file));
}
public FileReader(FileDescriptor fd) {
super(new FileInputStream(fd));
}
}
public class FileWriter extends OutputStreamWriter {
public FileWriter(String fileName) throws IOException {
super(new FileOutputStream(fileName));
}
public FileWriter(String fileName, boolean append) throws IOException {
super(new FileOutputStream(fileName, append));
}
public FileWriter(File file) throws IOException {
super(new FileOutputStream(file));
}
public FileWriter(File file, boolean append) throws IOException {
super(new FileOutputStream(file, append));
}
public FileWriter(FileDescriptor fd) {
super(new FileOutputStream(fd));
}
}
| 特性 | FileReader | FileWriter |
|---|---|---|
| 編碼指定 | ❌ 不支援,固定使用平台預設編碼 | |
| 追加模式 | — | ✅ 建構子支援 append 參數 |
| 緩衝支援 | ❌ 無內建緩衝,需自行包裝 BufferedReader/Writer | |
| 適用場景 | 簡單、小檔案、平台專用、編碼不敏感的文字處理 | |
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class FileReaderWriterDemo {
public static void main(String[] args) {
Path path = Path.of("file_rw_demo.txt");
// 寫入:使用 FileWriter(預設編碼)
try (FileWriter fw = new FileWriter(path.toFile())) {
fw.write("FileWriter 寫入測試\n");
fw.write("支援中文:測試內容\n");
fw.append("追加模式示範").append('\n');
} catch (IOException e) { e.printStackTrace(); }
// 讀取:使用 FileReader(預設編碼)
try (FileReader fr = new FileReader(path.toFile())) {
char[] buf = new char[64];
int len;
while ((len = fr.read(buf)) != -1) {
System.out.print(new String(buf, 0, len));
}
} catch (IOException e) { e.printStackTrace(); }
// ⚠️ 編碼陷阱示範:跨平台亂碼風險
demonstrateEncodingTrap(path);
}
private static void demonstrateEncodingTrap(Path path) {
String original = "編碼測試:中文內容";
// 以 UTF-8 寫入
try {
Files.writeString(path, original, StandardCharsets.UTF_8);
} catch (IOException e) { e.printStackTrace(); }
// 用 FileReader 讀取(若平台預設非 UTF-8 會亂碼)
try (FileReader fr = new FileReader(path.toFile())) {
char[] buf = new char[100];
int len = fr.read(buf);
System.out.println("FileReader 讀取: " + new String(buf, 0, len));
} catch (IOException e) { e.printStackTrace(); }
// 正確做法:指定編碼
try (var reader = new java.io.InputStreamReader(
new java.io.FileInputStream(path.toFile()), StandardCharsets.UTF_8)) {
char[] buf = new char[100];
int len = reader.read(buf);
System.out.println("指定 UTF-8 讀取: " + new String(buf, 0, len));
} catch (IOException e) { e.printStackTrace(); }
}
}
Java 7+ 強烈建議使用 java.nio.file.Files 進行檔案讀寫,優勢顯著:
// 寫入(自動建立目錄、指定編碼、可選選項)
Files.writeString(path, content, StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
// 讀取整個檔案為字串
String content = Files.readString(path, StandardCharsets.UTF_8);
// 逐行串流處理(大檔案友善)
try (var lines = Files.lines(path, StandardCharsets.UTF_8)) {
lines.filter(...).map(...).forEach(...);
}
// 取得 BufferedReader/Writer(指定編碼)
BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8);
BufferedWriter bw = Files.newBufferedWriter(path, StandardCharsets.UTF_8);
InputStreamReader/OutputStreamWriter 明確指定編碼,再考慮加上 BufferedReader/Writer。new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))。FileReader 與 FileWriter 是 Java 早期為了簡化字元檔案操作而設計的便利類,但其編碼死鎖與無緩衝特性在現代開發中已顯不足。理解其內部委派機制與局限,能幫助你在維護舊代碼時做出正確判斷,並在新專案中果斷選擇更強大的 NIO.2 API。