IO 流是 Java 處理裝置間數據傳輸的核心抽象。本筆記系統梳理流分類、字符/位元組流轉換、核心類 API、異常處理模式、緩衝與裝飾模式、標準流重定向,並附完整代碼示例,作為學習與複習參考。
| 維度 | 分類 | 典型類 | 適用場景 |
|---|---|---|---|
| 按數據單位 | 位元組流 | InputStream/OutputStream 子類 | 圖片、視頻、二進制文件、網路數據 |
| 字符流 | Reader/Writer 子類 | 文本文件、控制台輸入輸出、字符串處理 | |
| 按流向 | 輸入流 | InputStream/Reader | 從源讀取數據(檔案、網路、鍵盤) |
| 輸出流 | OutputStream/Writer | 向目的寫入數據(檔案、網路、螢幕) |
核心原則:字符流本質是位元組流經編碼表轉換而來(InputStreamReader/OutputStreamWriter),預設使用平台編碼,跨平台必須顯式指定 UTF-8。
Reader:read()、read(char[])、close()。Writer:write(int/char[]/String)、flush()、close()(關閉前自動 flush)。// 寫入(支援續寫 append=true)
try (FileWriter fw = new FileWriter("demo.txt", true)) {
fw.write("Hello World");
fw.write("\r\n"); // Windows 換行
} catch (IOException e) { e.printStackTrace(); }
// 讀取:單字符 / 字符陣列
try (FileReader fr = new FileReader("demo.txt")) {
int ch;
while ((ch = fr.read()) != -1) System.out.print((char)ch);
// 或批量讀取
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1) System.out.print(new String(buf, 0, len));
}
FileWriter fw = null;
try {
fw = new FileWriter("demo.txt");
fw.write("data");
} catch (IOException e) {
// 處理異常
} finally {
if (fw != null) try { fw.close(); } catch (IOException ignored) {}
}
// JDK 7+ 推薦 try-with-resources 自動關閉
try (FileWriter fw = new FileWriter("demo.txt")) { fw.write("data"); }
try (FileReader fr = new FileReader("src.txt");
FileWriter fw = new FileWriter("dest.txt")) {
char[] buf = new char[1024];
int len;
while ((len = fr.read(buf)) != -1) fw.write(buf, 0, len);
}
BufferedReader.readLine():按行讀取(不含換行符),返回 null 表示結束。BufferedWriter.newLine():跨平台寫入系統換行符(line.separator)。try (BufferedReader br = new BufferedReader(new FileReader("src.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("dest.txt"))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
}
繼承 BufferedReader,提供 getLineNumber()/setLineNumber() 追蹤行號。
結構:
Reader/Writer、InputStream/OutputStream。FileReader、FileInputStream 等具體源/目的。BufferedReader、InputStreamReader、OutputStreamWriter 等包裝類,構造器接收被裝飾對象。優勢:動態組合功能(緩衝、編碼轉換、行讀取),避免繼承爆炸,符合單一職責與開閉原則。
// 典型組合鏈:文件位元組流 → 編碼轉換 → 緩衝 → 行讀取
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream("file.txt"), "UTF-8"));
// 寫入位元組
try (FileOutputStream fos = new FileOutputStream("data.bin")) {
fos.write("abc".getBytes()); // 字符串轉位元組陣列
}
// 讀取:單位元組 / 位元組陣列 / available() 獲取剩餘長度
try (FileInputStream fis = new FileInputStream("data.bin")) {
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) != -1) System.out.write(buf, 0, len);
// available() 僅適用於文件/管道,網路流不可靠,不建議用於分配大陣列
}
try (FileInputStream fis = new FileInputStream("src.jpg");
FileOutputStream fos = new FileOutputStream("dest.jpg")) {
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) != -1) fos.write(buf, 0, len);
}
同字符緩衝流,裝飾位元組流提供 8KB 緩衝區,複製大文件效率顯著提升。
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("dest.jpg"))) {
byte[] buf = new byte[1024];
int len;
while ((len = bis.read(buf)) != -1) bos.write(buf, 0, len);
}
InputStreamReader(InputStream in, String charset):位元組流 → 字符流,指定編碼。OutputStreamWriter(OutputStream out, String charset):字符流 → 位元組流,指定編碼。應用場景:指定 UTF-8 讀寫文本、鍵盤輸入按行處理、標準流重定向。
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
String line;
while ((line = br.readLine()) != null) {
if ("over".equals(line)) break;
bw.write(line.toUpperCase());
bw.newLine();
bw.flush();
}
}
System.setIn(InputStream)、System.setOut(PrintStream) 可改變標準輸入/輸出裝置。
// 將鍵盤輸入重定向為文件,控制台輸出重定向為文件 → 實現文件複製
System.setIn(new FileInputStream("src.txt"));
System.setOut(new PrintStream(new FileOutputStream("dest.txt")));
// 此後 System.in 讀取來自 src.txt,System.out 寫入 dest.txt
InputStream/Reader),目的→輸出流(OutputStream/Writer)。Reader/Writer);二進制→位元組流(InputStream/OutputStream)。FileInputStream/FileReader、FileOutputStream/FileWriter。System.in(位元組)→轉換→BufferedReader。System.out(位元組)→轉換→BufferedWriter/PrintStream。ByteArrayInputStream/StringReader、ByteArrayOutputStream/StringWriter。Socket.getInputStream()/getOutputStream()。BufferedInputStream/BufferedReader、BufferedOutputStream/BufferedWriter;需指定編碼→套 InputStreamReader/OutputStreamWriter。try (BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("utf8.txt"), "UTF-8"))) {
bw.write("中文測試");
bw.newLine();
}
FileWriter 無法指定編碼(固定平台預設),必須通過 OutputStreamWriter 包裝 FileOutputStream 實現。
Java IO 體系雖類繁多,但遵循「源/目的 → 數據類型 → 裝置 → 功能增強」四步選型法則,配合裝飾模式動態組合,即可應對所有讀寫場景。重點掌握:字符流處理文本(指定 UTF-8)、位元組流處理二進制、緩衝流提升效率、轉換流橋接編碼、try-with-resources 保證資源釋放。