Java IO 體系中,字節流(InputStream/OutputStream)與字符流(Reader/Writer)是兩大根接口,理解其差異、轉換橋樑與適用場景,是高效處理文件、網絡、序列化的基石。
| 維度 | 字節流 | 字符流 |
|---|---|---|
| 基本單位 | 字節(8 bit) | 字符(16 bit Unicode) |
| 處理對象 | 圖片、視頻、音頻、二進制文件、網絡流 | 文本文件、字符串、控制台輸入輸出 |
| 編碼轉換 | 無,直接讀寫原始字節 | 內建編碼/解碼(默認平台編碼或指定 Charset) |
| 緩衝機制 | 通常不自帶緩衝,需套 BufferedInputStream | 通常不自帶緩衝,需套 BufferedReader/Writer |
| 核心抽象類 | InputStream / OutputStream | Reader / Writer |
| 典型實現 | FileInputStream, ByteArrayInputStream, Socket.getInputStream() | FileReader, StringReader, InputStreamReader |

InputStreamReader / OutputStreamWriter字符流本質是字節流的裝飾器,負責「字節 ⇄ 字符」轉碼:
// 字節流 → 字符流(解碼)
Reader reader = new InputStreamReader(new FileInputStream("data.txt"), "UTF-8");
// 字符流 → 字節流(編碼)
Writer writer = new OutputStreamWriter(new FileOutputStream("out.txt"), "UTF-8");
務必顯式指定 Charset,否則依賴平台默認編碼(Windows GBK,Linux UTF-8),導致跨平台亂碼。
flush() 陷阱字符流常搭配 BufferedWriter,數據先寫入內存緩衝區,滿或調用 flush() 才真正落盤。
BufferedWriter bw = new BufferedWriter(new FileWriter("log.txt"));
bw.write("第一行");
bw.flush(); // 強制刷新,確保即時可見
bw.write("第二行");
bw.close(); // 關閉會自動 flush
忘記 flush/close 是文件寫入「丟數據」的首因。
FileChannel.transferTo()(NIO 零拷貝)或 BufferedInputStream/OutputStream 大緩衝區(8KB+)。BufferedReader.readLine() 或 Files.lines() (Stream)。| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
new FileReader("中文.txt") | 隱式使用平台編碼,跨平台亂碼 | new InputStreamReader(new FileInputStream("中文.txt"), "UTF-8") |
fw.write(str); // 無 flush/close | 數據停留在緩衝區,進程崩潰丟失 | try-with-resources 自動 close,或顯式 flush() |
while((c = in.read()) != -1) | 單字節讀取,極慢 | 用 BufferedInputStream + byte[] buf = new byte[8192] |
InputStreamReader/OutputStreamWriter 必須指定編碼。try-with-resources 保證資源釋放。FileChannel 或 mmap。