處理大文件時,傳統 FileInputStream、RandomAccessFile 頻繁讀寫磁盤,性能瓶頸明顯。Java NIO 提供的 內存映射文件 將文件直接映射到內存區域,讀寫操作變為內存操作,速度提升數量級。
MappedByteBuffer 通過 FileChannel.map() 將文件部分或全部映射到堆外內存,視為字節數組直接操作,OS 負責頁面調度與回寫,避免用戶態/內核態頻繁拷貝。
// 1. FileInputStream 直接讀取
FileInputStream fis = new FileInputStream("/path/to/file");
while ((n = fis.read()) >= 0) { sum += n; }
// 耗時:1464 ms
// 2. BufferedInputStream 緩衝讀取
BufferedInputStream bis = new BufferedInputStream(fis);
while ((n = bis.read()) >= 0) { sum += n; }
// 耗時:72 ms
// 3. MappedByteBuffer 內存映射
MappedByteBuffer buffer = new RandomAccessFile(file, "rw")
.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, fileSize);
for (int i = 0; i < fileSize; i++) {
n = 0xFF & buffer.get(i);
sum += n;
}
// 耗時:25 ms
結論:內存映射較無緩衝流快 ~3 倍,較裸流快 ~60 倍。若去除數據處理邏輯(僅遍歷),差距更大(1458ms vs 67ms vs 8ms)。
import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class MappedFileBenchmark {
public static void main(String[] args) throws IOException {
String filePath = "/home/tobacco/test/res.txt";
int fileSize = 1253244; // 文件大小
// 方案 1:FileInputStream
benchmark("FileInputStream", () -> {
try (FileInputStream fis = new FileInputStream(filePath)) {
int n;
while ((n = fis.read()) >= 0) { /* sum += n; */ }
}
});
// 方案 2:BufferedInputStream
benchmark("BufferedInputStream", () -> {
try (FileInputStream fis = new FileInputStream(filePath);
BufferedInputStream bis = new BufferedInputStream(fis)) {
int n;
while ((n = bis.read()) >= 0) { /* sum += n; */ }
}
});
// 方案 3:MappedByteBuffer
benchmark("MappedByteBuffer", () -> {
try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw");
FileChannel channel = raf.getChannel()) {
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, fileSize);
for (int i = 0; i < fileSize; i++) { /* buffer.get(i); */ }
}
});
}
static void benchmark(String name, Runnable task) {
long start = System.currentTimeMillis();
task.run();
System.out.printf("%s: %d ms%n", name, System.currentTimeMillis() - start);
}
}
force() 強制刷盤FileChannel.MapMode.READ_ONLY、PRIVATE(寫時復制)模式內存映射文件是 Java 處理大文件的利器,通過 OS 頁面緩存機制實現零拷貝訪問,對於 GB 級文件隨機讀寫場景極具優勢。實際項目中建議封裝為工具類,統一管理映射生命週期與異常處理。