`FileOutputStream` — 位元組輸出流,寫入原始二進制資料到檔案。字串需先 `.getBytes(Charset)` 轉換。
public class WriteFileLegacy {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
File file = new File("data.txt");
fos = new FileOutputStream(file); // 預設覆蓋
// new FileOutputStream(file, true) // 追加模式
String content = "Hello, FileOutputStream!";
fos.write(content.getBytes(StandardCharsets.UTF_8));
fos.flush(); // 強制刷新緩衝區
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try { fos.close(); } catch (IOException ignored) {}
}
}
}
}
❌ **缺點**:樣板碼多、易忘記 close、資源洩漏風險。
public class WriteFileModern {
public static void main(String[] args) {
File file = new File("data.txt");
String content = "Hello, try-with-resources!";
// 自動關閉實作 AutoCloseable 的資源
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(content.getBytes(StandardCharsets.UTF_8));
// 無需手動 flush/close,離開區塊自動執行
} catch (IOException e) {
e.printStackTrace();
}
}
}
✅ **優點**:簡潔、安全、編譯器保證關閉、支援多資源 `try (A a = ...; B b = ...)`。
import java.nio.file.*;
import java.util.List;
public class WriteFileNio {
public static void main(String[] args) {
Path path = Paths.get("data.txt");
String content = "Hello, NIO.2 Files.write!";
List lines = List.of("Line 1", "Line 2", "Line 3");
try {
// 1. 寫入單一字串 (覆蓋)
Files.writeString(path, content, StandardCharsets.UTF_8); // JDK 11+
// 2. 寫入多行 (覆蓋)
Files.write(path, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
// 3. 追加模式
Files.write(path, List.of("Append line"), StandardCharsets.UTF_8, StandardOpenOption.APPEND);
// 4. 位元組陣列
Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
} catch (IOException e) {
e.printStackTrace();
}
}
}
| 需求 | FileOutputStream | Files.write |
|---|---|---|
| 覆蓋寫入 | `new FileOutputStream(file)` | `CREATE, TRUNCATE_EXISTING` (預設) |
| 追加寫入 | `new FileOutputStream(file, true)` | `APPEND` |
| 建立新檔/覆蓋 | 預設行為 | `CREATE, TRUNCATE_EXISTING` |
| 僅建立新檔(存在報錯) | 不支援 | `CREATE_NEW` |
| 同步刷新到磁碟 | `fos.getFD().sync()` | `SYNC` / `DSYNC` 選項 |
new BufferedOutputStream(new FileOutputStream(file)) 減少系統呼叫。| 方式 | 耗時 (ms) | 備註 |
|---|---|---|
| FileOutputStream 直寫 | ~1200 | 無緩衝,系統呼叫頻繁 |
| BufferedOutputStream 8KB | ~180 | 標準生產寫法 |
| Files.write (位元組陣列) | ~150 | 內部最佳化,最簡潔 |
| Files.writeString (JDK 11) | ~160 | 字串直寫 |
| MappedByteBuffer (記憶體映射) | ~90 | 超大檔案、隨機寫入最強 |
| 例外 | 原因 | 處理 |
|---|---|---|
| FileNotFoundException | 父目錄不存在、權限不足、路徑是目錄 | `file.getParentFile().mkdirs()`、檢查權限 |
| IOException: No space left | 磁碟滿 | 監控磁碟、清理空間、降級處理 |
| SecurityException | SecurityManager 禁止寫入 | 調整策略或簽名 Jar |