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

Java I/O 流體系深度解析:從基礎概念到高效讀寫實戰

     編輯:Java 相關知識

流的核心抽象

Java I/O 採用流模型:資料像水流一樣在來源與目的地之間傳輸。核心在於裝飾者模式,透過層層包裝賦予額外功能 (緩衝、轉碼、物件序列化等)。

四大流家族

維度位元組流字元流
基本單位Byte (8 bits)Char (16 bits, UTF-16)
抽象基類`InputStream` / `OutputStream``Reader` / `Writer`
適用場景圖片、影音、二進位檔、網路傳輸文字檔、XML、JSON、字串處理
轉換橋樑`InputStreamReader` / `OutputStreamWriter` (指定 Charset)

關鍵裝飾者類別

  • 緩衝:`BufferedInputStream`、`BufferedReader` — 大幅減少系統呼叫,必加。
  • 資料型別:`DataInputStream`/`DataOutputStream` (基本型別)、`ObjectInputStream`/`ObjectOutputStream` (序列化)。
  • 列印:`PrintStream` (`System.out`)、`PrintWriter` — 自動 flush、不拋出 IOException。
  • 檔案:`FileInputStream`、`FileReader`、`FileWriter` — 節點流,直接操作檔案。

實戰範例:高效讀寫最佳實踐

1. 讀取文字檔 (推薦 Java 7+ try-with-resources)

// 逐行讀取,自動關閉資源
public List<String> readLines(Path path, Charset charset) throws IOException {
    try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
        return reader.lines().collect(Collectors.toList()); // Java 8 Stream API
    }
}

// 或手動處理
try (BufferedReader br = new BufferedReader(
        new InputStreamReader(new FileInputStream("data.txt"), StandardCharsets.UTF_8))) {
    String line;
    while ((line = br.readLine()) != null) {
        process(line);
    }
}

2. 寫入文字檔

public void writeLines(Path path, List<String> lines, Charset charset) throws IOException {
    try (BufferedWriter writer = Files.newBufferedWriter(path, charset,
            StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
        for (String line : lines) {
            writer.write(line);
            writer.newLine(); // 平台無關換行
        }
    }
}

3. 二進位檔案複製 (NIO.2 高效)

// 內部使用零拷貝 或直接緩衝區傳輸,極快
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);

// 手動緩衝複製 (傳統 IO)
try (InputStream in = new BufferedInputStream(new FileInputStream(src));
     OutputStream out = new BufferedOutputStream(new FileOutputStream(dest))) {
    byte[] buffer = new byte[8192];
    int len;
    while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
    }
}

4. 標準輸入互動 (Scanner vs BufferedReader)


// 簡單解析用 Scanner
try (Scanner sc = new Scanner(System.in, StandardCharsets.UTF_8.name())) {
    System.out.print("請輸入長方形長: ");
    double len = sc.nextDouble();
    System.out.print("請輸入寬: ");
    double wid = sc.nextDouble();
    System.out.printf("面積: %.2f%n", len * wid);
}

// 高效能/大量資料用 BufferedReader
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
    System.out.print("輸入: ");
    String input = br.readLine();
}

進階主題:NIO 與 NIO.2

  • Channel & Buffer:`FileChannel`、`ByteBuffer` — 非阻塞、記憶體映射檔 (`MappedByteBuffer`)、分散/聚集讀寫。
  • Selector:單執行緒管理多 Channel,高併發網路伺服器核心 (Netty 底層基礎)。
  • Path & Files API (NIO.2):現代檔案系統操作 (屬性、走訪、監聽 `WatchService`)。

常見錯誤與效能建議

  1. ❌ 直接用 `FileReader`/`FileWriter` (無緩衝、預設編碼不可控) → ✅ 显式指定 `StandardCharsets.UTF_8` + `BufferedReader/Writer`。
  2. ❌ 單位元組 `read()`/`write()` 循環 → ✅ 使用 `byte[8192]` 緩衝陣列或 `transferTo()`。
  3. ❌ 忘記 `close()` → ✅ 強制使用 `try-with-resources`。
  4. ❌ 序列化 `ObjectOutputStream` 長期儲存 → ✅ 改用 JSON/Protobuf/Avro,版本相容性更好。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved