目前Java中最IO有多種文件讀取的方法,本文章對比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,讓我們知道到底怎麼能寫出性能高的文件讀取代碼。
package com.seeyon.nio;
import org.junit.Test;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
/**
* Created by yangyu on 16/12/28.
*/
/**
* 比較Stream流,NIO ByteBuffer,NIO MappedByteBuffer性能對比
* 其中Stream最慢,NIO MappedByteBuffer最快
* Stream:1000ms
* NIO ByteBuffer:220ms
* NIO MappedByteBuffer:112ms
*/
public class Compare {
/**
* 使用stream作為IO流讀取和寫入文件
* 速度:1000ms左右
*
* @throws IOException
*/
@Test
public void useStream() throws IOException {
long startTime = System.currentTimeMillis();
/**
* 4000000個整數長度的文件
*/
int num = 2000 * 2000;
/**
* 帶緩沖的輸出流,寫文件
*/
DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("/Users/yangyu/Downloads/compare.tmp")));
for (int i = 0; i < num; i++) {
dataOutputStream.writeInt(i);
}
dataOutputStream.close();
int data = 0;
/**
* 帶緩沖的輸入流,讀文件
*/
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("/Users/yangyu/Downloads/compare.tmp")));
try {
while (true) {
data = in.readInt();
}
} catch (EOFException e) {
System.out.println("讀取完成"+data);
}
in.close();
long endTime = System.currentTimeMillis();
System.out.println("ms:" + (endTime - startTime));
}
/**
* 使用NIO ByteBuffer
* 時間:220ms
* @throws IOException
*/
@Test
public void useNioByteBuffer() throws IOException {
long startTime = System.currentTimeMillis();
int num = 2000*2000;
/**
* 文件輸出流
*/
FileOutputStream fileOutputStream = new FileOutputStream("/Users/yangyu/Downloads/compare.tmp");
/**
* NIO Channel 通道
*/
FileChannel fileChannel = fileOutputStream.getChannel();
/**
* ByteBuffer緩沖區
*/
ByteBuffer buffer = ByteBuffer.allocate(num*5);
for (int i = 0; i < num; i++) {
buffer.putInt(i);
}
/**
* 為寫做准備
*/
buffer.flip();
/**
* 寫操作
*/
fileChannel.write(buffer);
fileChannel.close();
/**
* 緩沖區
*/
ByteBuffer buffer1 = ByteBuffer.allocate(num*5);
/**
* 文件輸入流
*/
FileInputStream in = new FileInputStream("/Users/yangyu/Downloads/compare.tmp");
/**
* 輸入通道
*/
FileChannel fin = in.getChannel();
/**
* 為讀取做准備
*/
buffer1.clear();
System.out.println(buffer1.limit());
/**
* 讀取
*/
fin.read(buffer1);
fin.close();
long endTime = System.currentTimeMillis();
System.out.println("ms:" + (endTime - startTime));
buffer1.flip();
System.out.println(buffer1.limit());
}
/**
* 使用MappedByteBuffer,通過FileChannel將文件映射到內存
* 時間:112ms
* @throws IOException
*/
@Test
public void useRandomAccess() throws IOException {
long startTime = System.currentTimeMillis();
int num = 2000*2000;
/**
* 使用可隨機訪問位置的RandomAccessFile
*/
RandomAccessFile file = new RandomAccessFile("/Users/yangyu/Downloads/compare.tmp","rw");
/**
* 獲取通道Channel
*/
FileChannel fileChannel = file.getChannel();
/**
* 將文件映射到緩沖區MappedByteBuffer
*/
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE,0,num*4);
/**
* 寫文件
*/
for (int i = 0; i < num; i++) {
mappedByteBuffer.putInt(i);
}
fileChannel.close();
int data=0;
RandomAccessFile file1 = new RandomAccessFile("/Users/yangyu/Downloads/compare.tmp","rw");
FileChannel fc = file1.getChannel();
MappedByteBuffer mappedByteBuffer1 = fc.map(FileChannel.MapMode.READ_WRITE,0,file1.length());
/**
* 讀文件
*/
while (mappedByteBuffer1.hasRemaining()){
data = mappedByteBuffer1.getInt();
}
fc.close();
long endTime = System.currentTimeMillis();
System.out.println("ms:" + (endTime - startTime));
System.out.println(data);
}
}
結論非常明顯啦,以後再使用IO讀寫文件的時候,多使用NIO MappedByteBuffer吧,畢竟NIO比老IO性能好太多啦。