對比三種文件讀寫方式性能,測試數據量:2000×2000 = 400 萬個整數。完整 JUnit 測試代碼如下:
@Test
public void useStream() throws IOException {
long start = System.currentTimeMillis();
int num = 2000 * 2000;
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(FILE)));
for (int i = 0; i < num; i++) out.writeInt(i);
out.close();
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(FILE)));
try { while (true) in.readInt(); } catch (EOFException ignored) {}
in.close();
System.out.println("Stream ms: " + (System.currentTimeMillis() - start)); // ~1000ms
}
@Test
public void useNioByteBuffer() throws IOException {
long start = System.currentTimeMillis();
int num = 2000 * 2000;
FileChannel fcOut = new FileOutputStream(FILE).getChannel();
ByteBuffer buf = ByteBuffer.allocate(num * 5);
for (int i = 0; i < num; i++) buf.putInt(i);
buf.flip();
fcOut.write(buf);
fcOut.close();
FileChannel fcIn = new FileInputStream(FILE).getChannel();
ByteBuffer bufIn = ByteBuffer.allocate(num * 5);
fcIn.read(bufIn);
fcIn.close();
System.out.println("NIO ByteBuffer ms: " + (System.currentTimeMillis() - start)); // ~220ms
}
@Test
public void useRandomAccess() throws IOException {
long start = System.currentTimeMillis();
int num = 2000 * 2000;
RandomAccessFile raf = new RandomAccessFile(FILE, "rw");
FileChannel fc = raf.getChannel();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, num * 4);
for (int i = 0; i < num; i++) mbb.putInt(i);
fc.close();
// 讀取驗證...
System.out.println("MappedByteBuffer ms: " + (System.currentTimeMillis() - start)); // ~112ms
}
MappedByteBuffer (112ms) > NIO ByteBuffer (220ms) > Stream (1000ms)。記憶體映射文件直接操作用戶空間,省去核心態拷貝,性能碾壓傳統 IO。未來文件讀寫優先考慮 MappedByteBuffer 或 NIO 通道方式。