標籤:記憶體 unit rtt load sys 檔案 created buffer 隨機
目前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效能好太多啦。
Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer效能對比