Java IO 是程序與外部世界 (文件、網絡、設備) 交互的橋樑。本文按**流向**、**數據單位**、**功能角色**三個維度,系統梳理 java.io 包核心類體系、關鍵 API、典型用法、裝飾者模式精髓,並對比 NIO.2 現代化 API。
| 抽象基類 | 流向 | 數據單位 | 核心子類代表 |
|---|---|---|---|
InputStream | 輸入 (讀) | 字節 (byte) | FileInputStream、ByteArrayInputStream、DataInputStream |
OutputStream | 輸出 (寫) | 字節 (byte) | FileOutputStream、ByteArrayOutputStream、DataOutputStream |
Reader | 輸入 (讀) | 字符 (char, UTF-16) | FileReader、BufferedReader、InputStreamReader |
Writer | 輸出 (寫) | 字符 (char, UTF-16) | FileWriter、BufferedWriter、OutputStreamWriter |
字節流 處理二進制數據 (圖片、視頻、序列化對象);字符流 專為文本設計,內部自動處理編碼轉換,**中文場景首選字符流避免亂碼**。
File **不屬於流體系**,僅封裝路徑元數據 (不讀寫內容)。
new File(String pathname); new File(File parent, String child); new File(String parent, String child); new File(URI uri);
| 方法 | 返回值 | 說明 |
|---|---|---|
exists() | boolean | 路徑是否存在 |
isFile() / isDirectory() | boolean | 文件/目錄判斷 |
getAbsolutePath() | String | 絕對路徑 |
getName() | String | 文件名 |
length() | long | 文件大小 (字節) |
lastModified() | long | 最後修改時間戳 |
list() / listFiles() | String[] / File[] | 列出子項 (可配合 FilenameFilter/FileFilter 過濾) |
mkdir() / mkdirs() | boolean | 創建目錄 (單級/多級) |
createNewFile() | boolean | 創建空文件 (原子操作) |
delete() | boolean | 刪除 (目錄必須為空) |
renameTo(File dest) | boolean | 重命名/移動 |
FileInputStream / FileOutputStream:直接操作磁盤文件,**構造方法拋 FileNotFoundException**。ByteArrayInputStream / ByteArrayOutputStream:內存緩衝區作為數據源/目的地,**無需關閉**。// InputStream int read(); // 讀單字節,返回 0-255 或 -1 (EOF) int read(byte[] b); // 批量讀入數組,返回實際讀取字節數 int read(byte[] b, int off, int len); // 指定偏移長度 long skip(long n); // 跳過 n 字節 int available(); // 剩餘可讀字節數 (不一定準確) void close(); // 關閉釋放資源 // OutputStream void write(int b); // 寫單字節 (低 8 位) void write(byte[] b); // 寫數組 void write(byte[] b, int off, int len); void flush(); // 強制刷新緩衝區 void close(); // 關閉 (含 flush)
| 處理流 | 被裝飾流 | 增強功能 | 典型組合 |
|---|---|---|---|
BufferedInputStream/BufferedOutputStream | 任意 InputStream/OutputStream | **緩衝區 (默認 8KB)**,大幅減少系統調用,IO 性能倍增器 | new BufferedInputStream(new FileInputStream("a.dat")) |
DataInputStream/DataOutputStream | 任意 InputStream/OutputStream | 按基本類型讀寫 (readInt()/writeInt() 等),**跨平台二進制格式** | 網絡協議、對象序列化 |
ObjectInputStream/ObjectOutputStream | 任意 InputStream/OutputStream | 對象序列化/反序列化 (Serializable) | RPC、分布式會話 |
GZIPInputStream/GZIPOutputStream | 任意 InputStream/OutputStream | 流式壓縮/解壓 | HTTP 壓縮傳輸 |
| 舊 API (java.io) | 新 API (java.nio.file) | 優勢 |
|---|---|---|
new File(path) | Paths.get(path) / Path | 不可變、線程安全、豐富路徑操作 |
file.listFiles() | Files.list(dir) / Files.walk(dir) | 流式、惰性、支援並行流 |
file.renameTo() | Files.move(src, target, REPLACE_EXISTING) | 原子移動、跨文件系統、異常信息豐富 |
| 手動讀寫流 | Files.readAllLines()/Files.write()/Files.newBufferedReader() | 一行代碼搞定、自動資源管理 |
| 無 | Files.walkFileTree() | 訪問者模式遞歸、完整異常控制 |
| 無 | WatchService | 文件系統事件監聽 (熱加載、同步) |
Files.newBufferedReader(path, StandardCharsets.UTF_8) + try-with-resources。Files.newInputStream(path) + BufferedInputStream。Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING) (底層零拷貝 sendfile)。getClass().getResourceAsStream("/config.properties") (ClassPath 資源)。Serializable、聲明 serialVersionUID、慎用 transient。try (Resource r = ...) { }**,JDK 9+ 可 try (var in = Files.newInputStream(p)) { }。Java IO 從 File 元數據操作、四大流體系、裝飾者模式靈活組合,演進至 NIO.2 Path/Files/WatchService 現代化 API。**核心不變:流是有序數據序列,裝飾者賦能,編碼轉換是字符流靈魂**。選對工具 (NIO.2 為主、舊 IO 為輔),寫出健壯、高性能、跨平台的 IO 代碼。