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

Java 文件按字節讀取:FileInputStream 高效實現與避坑指南

     編輯:Java 相關知識

核心 API

FileInputStream 是字節輸入流基石,關鍵方法:

  • int read():讀取單字節,返回 0-255,末尾返回 -1
  • int read(byte[] b):批量讀入字節數組,返回實際讀取字節數
  • int available():返回剩餘可讀字節數(僅適用普通文件)

簡潔實現:一次性讀入內存

public byte[] readAllBytes(String filePath) throws IOException {
    File file = new File(filePath);
    try (FileInputStream in = new FileInputStream(file)) {
        // 關鍵:available() 獲取文件大小,分配精確數組
        byte[] bytes = new byte[in.available()];
        int read = in.read(bytes);
        if (read != bytes.length) {
            throw new IOException("讀取不完整: 預期 " + bytes.length + " 實際 " + read);
        }
        return bytes;
    }  // try-with-resources 自動關閉
}

適用場景與限制

場景是否適用說明
小文件 (< 10MB)✅ 完美一次性讀入,代碼簡潔
大文件 (> 100MB)❌ 禁止OOM 風險,需分塊讀取/流式處理
網絡流/管道/設備文件❌ 禁止available() 返回 0 或不準確
需邊讀邊處理❌ 不適用用緩衝流 + 循環 read()

大文件正確姿勢:分塊讀取

public void processLargeFile(String filePath, Consumer chunkHandler) throws IOException {
    final int BUFFER_SIZE = 8192;  // 8KB 緩衝區
    try (FileInputStream in = new FileInputStream(filePath);
         BufferedInputStream bin = new BufferedInputStream(in, BUFFER_SIZE)) {
        byte[] buffer = new byte[BUFFER_SIZE];
        int len;
        while ((len = bin.read(buffer)) != -1) {
            // 處理實際讀取的字節
            chunkHandler.accept(Arrays.copyOf(buffer, len));
        }
    }
}

進階:NIO 零拷貝(超大文件/高性能)

public void readWithNIO(String filePath) throws IOException {
    try (FileChannel channel = FileChannel.open(Paths.get(filePath), StandardOpenOption.READ)) {
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
        // 直接操作 buffer,OS 負責頁面調度,不佔用 JVM 堆
    }
}

常見錯誤總結

  1. 忽略 read() 返回值:以為滿數組,實際可能部分讀取
  2. 大文件用 available() 分配數組:直接 OOM
  3. 忘記關閉流:文件句柄洩漏,務必用 try-with-resources
  4. 字符文件用字節流:亂碼風險,應用 FileReader/BufferedReader

總結

小文件用 in.read(new byte[in.available()]) 一行搞定;大文件用緩衝流分塊或 NIO 內存映射;永遠用 try-with-resources 管理資源。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved