首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 寫入檔案的四種主流方式完整比較與最佳實踐

     編輯:Java 相關知識

前言

Java I/O 體系龐大,寫入檔案的方式不下十種。本文精選四種最常見、最具代表性的寫法:FileWriter、BufferedWriter、FileOutputStream(傳統與 Try-with-resources)、Files.write() (NIO.2),並從適用場景、效能、資源管理、編碼控制等維度深度比較,助你根據專案需求選擇最佳方案。

方式一:FileWriter(字元流,直接覆寫/附加)

基本用法

File file = new File("demo.txt");
try (FileWriter fw = new FileWriter(file)) { // 預設覆寫
    fw.write("Hello World");
} catch (IOException e) {
    e.printStackTrace();
}

附加模式

// 第二個參數 true 表示 append
try (FileWriter fw = new FileWriter(file, true)) {
    fw.write("\nAppend line");
}

優缺點

  • ✅ 簡單直觀,適合少量文字、臨時寫入。
  • ❌ 無緩衝,逐字寫入磁碟,大量資料效能差。
  • ❌ 編碼鎖定為平台預設(Windows 通常為 Big5/GBK,Linux 為 UTF-8),跨平台易亂碼。

方式二:BufferedWriter + FileWriter(字元流 + 緩衝)

try (FileWriter fw = new FileWriter(file);
     BufferedWriter bw = new BufferedWriter(fw)) {
    bw.write("Line 1");
    bw.newLine(); // 跨平台換行
    bw.write("Line 2");
} catch (IOException e) {
    e.printStackTrace();
}

優缺點

  • ✅ 8KB 預設緩衝,大幅減少系統呼叫,效能優於裸 FileWriter。
  • ✅ 提供 newLine() 自動處理 \r\n / \n 差異。
  • ❌ 仍受限於 FileWriter 的平台預設編碼。

方式三:FileOutputStream(位元組流,完全掌控編碼)

傳統寫法 (JDK 6/7)

FileOutputStream fos = null;
try {
    fos = new FileOutputStream(file);
    byte[] data = "內容".getBytes("UTF-8"); // 明確指定編碼
    fos.write(data);
    fos.flush();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fos != null) try { fos.close(); } catch (IOException ignored) {}
}

Try-with-resources (JDK 7+ 推薦)

try (FileOutputStream fos = new FileOutputStream(file)) {
    fos.write("內容".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
    e.printStackTrace();
}

優缺點

  • ✅ 可精確指定編碼(StandardCharsets.UTF_8),跨平台最穩定。
  • ✅ 處理二進位檔案(圖片、壓縮包)必須使用位元組流。
  • ❌ 手動轉換字串為 byte[],稍顯繁瑣。

方式四:Files.write() (NIO.2, JDK 7+)

import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

List<String> lines = Arrays.asList("Line 1", "Line 2", "Line 3");
Files.write(Paths.get("nio.txt"), lines, StandardCharsets.UTF_8,
        StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
// 附加模式:StandardOpenOption.APPEND

優缺點

  • ✅ 一行程式碼完成開啟、寫入、關閉、編碼指定、原子性選項。
  • ✅ 支援 StandardOpenOption 組合:APPEND, SYNC, DSYNC 等。
  • ✅ 內部使用緩衝,效能優異。
  • ❌ 僅支援 List<String>、byte[]、Iterable<Byte>,不支援串流式寫入超大檔案(需搭配 Files.newBufferedWriter)。

效能微基準測試參考 (寫入 10MB 文字)

方式耗時 (ms)備註
FileWriter~1,200無緩衝,頻繁系統呼叫
BufferedWriter~1808KB 緩衝
FileOutputStream + byte[]~150單次寫入
Files.write()~160內部緩衝 + 原子選項

環境:SSD、JDK 17、Windows 11,僅供相對參考。

最佳實踐建議

  1. 文字檔、小檔案、需跨平台:首選 Files.write(..., StandardCharsets.UTF_8, ...)。
  2. 大文字檔、需串流處理:Files.newBufferedWriter(path, StandardCharsets.UTF_8) 取得 BufferedWriter 逐行寫入。
  3. 二進位檔案:Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING) 或 FileOutputStream。
  4. 高併發寫入同一檔案:需外部鎖(檔案鎖 FileChannel.lock() 或資料庫協調),單純 Java I/O 無法保證原子性。
  5. 編碼統一:專案全域強制 StandardCharsets.UTF_8,杜絕平台預設編碼。

常見陷阱提醒

  • FileWriter(file, true) 附加模式下,若檔案不存在會自動建立;但目錄不存在會拋 FileNotFoundException,需先 file.getParentFile().mkdirs()。
  • Files.write 預設 CREATE, TRUNCATE_EXISTING, WRITE,若需保留舊內容必須加 APPEND。
  • Windows 上 Files.write(..., SYNC) 會強制刷入實體磁碟,效能大幅下降,非關鍵資料勿用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved