目前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性能好太多啦。