類繼承體系速覽
java.lang.Object
└─ java.io.Reader (抽象基類,字符流)
└─ java.io.InputStreamReader (字節流→字符流橋梁,支援指定編碼)
└─ java.io.BufferedReader (緩衝字符流,提供 readLine() 高效逐行讀取)
└─ java.io.FileReader (InputStreamReader 子類,預設平台編碼,構造參數為 File/String)
核心類職責解析
| 類 | 核心能力 | 典型場景 |
| InputStreamReader | 字節流解碼為字符流,可指定 Charset(UTF-8/GBK 等) | 跨平台文本讀取、網絡流解碼、指定編碼文件 |
| BufferedReader | 緩衝區批量讀取,提供 readLine()、read(char[]) | 大文件逐行處理、控制台交互、高頻讀取優化 |
| FileReader | 便利構造(File/String),內部委派 FileInputStream,編碼固定為平台預設 | 簡單本地文件讀取,不需指定編碼時 |
為什麼要「雙層包裝」?
// 標準高效讀取鏈
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream("data.txt"), "UTF-8"
)
);
FileInputStream:底層字節源。
InputStreamReader:解碼器,將字節按指定編碼轉為字符。
BufferedReader:緩衝層,減少底層 read() 系統調用,提供逐行 API。
💡 原則:Reader 的每次 read() 都可能觸發底層字節讀取與解碼,開銷極大;BufferedReader 批量預讀,將開銷攤薄到緩衝區大小。
完整實戰代碼
場景 1:指定編碼讀取文件並逐行處理
public void readWithEncoding(String filePath, String charset) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream(filePath), charset))) {
String line;
while ((line = br.readLine()) != null) {
processLine(line); // 業務邏輯
}
} catch (IOException e) {
log.error("讀取失敗: {}", filePath, e);
}
}
場景 2:控制台交互讀取整行含空格
public String readConsoleLine() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
System.out.print("請輸入內容:");
return br.readLine(); // 讀取整行,包含空格
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
場景 3:資源路徑下文件讀取(ClassPath)
public void readClasspathResource(String resourceName) {
try (InputStream is = getClass().getResourceAsStream(resourceName);
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
log.error("資源讀取失敗: {}", resourceName, e);
}
}
編碼陷阱與最佳實踐
- ❌ 直接使用 FileReader:依賴平台預設編碼(Windows GBK,Linux UTF-8),跨平台極易產生亂碼。
- ✅ 顯式指定 StandardCharsets.UTF_8:確保行為一致,避免「開發正常、部署亂碼」。
- ⚠️ 二進制文件(圖片/視頻):禁止 使用 Reader 體系,必須用
InputStream/FileInputStream 純字節讀取。
Reader vs InputStream 根本差異
| 維度 | Reader 體系 | InputStream 體系 |
| 數據單位 | char (16-bit Unicode) | byte (8-bit) |
| 適用數據 | 文本、字符 | 二進制、圖片、音視頻、網絡字節流 |
| 編碼轉換 | 內建解碼器 | 無,需外部轉換 |
| 緩衝增強 | BufferedReader | BufferedInputStream |
總結
掌握 InputStreamReader(解碼橋梁)與 BufferedReader(緩衝加速)的協作模式,始終顯式指定編碼,是 Java 高健壯性文本處理的基石。