Java : NIO
http://yamarou.at.infoseek.co.jp/javanawake/022.html
java.ioとjava.nioのファイル読み込み速度を比較しているのだけれど、ちょっとプログラムがアレだなと思ったので、書き直してみた。
主要な部分だけを比較すると、元の記事のプログラムは、
/** * filePathのファイルを読み込んでbyte配列に格納して返す。java.ioを使う。 * @param filePath * @return ファイルの中身 */ public static byte[] readUsingIO(String filePath) throws IOException { BufferedInputStream in = new BufferedInputStream( new FileInputStream(filePath)); byte[] data = new byte[in.available()]; int size = in.read(data); System.out.println("size="+size); return data; } /** * filePathのファイルを読み込んでbyte配列に格納して返す。java.nioを使う。 * @param filePath * @return ファイルの中身 */ public static byte[] readUsingNIO(String filePath) throws IOException { FileInputStream in = new FileInputStream(filePath); FileChannel channel = in.getChannel(); ByteBuffer buf = ByteBuffer.allocateDirect((int)channel.size()); channel.read(buf); buf.flip(); byte[] data = new byte[buf.capacity()]; buf.get(data); channel.close(); return data; }
となっているわけだけれど、ダイレクトバッファを使っている点とバッファに読み込んだデータを再度配列に書いている点。後、FileInputStream#read()は配列に直接書き込むのに対して、FileChannel#read()はByteBufferのインターフェースを介して書き込むのでその分効率が悪いわけだから、FileChannel#read()を使うのはよくない。
というわけで、書き直したプログラムが以下。ファイルのメモリマップを取得して、そこから直接byte配列にコピーするという処理。
/** * filePathのファイルを読み込んでbyte配列に格納して返す。java.nioを使う。 * @param filePath * @return ファイルの中身 */ public static byte[] readUsingNIO(String filePath) throws IOException { File file = new File(filePath); byte[] data = new byte[(int) file.length()]; FileInputStream in = new FileInputStream(file); FileChannel channel = in.getChannel(); ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY,0,file.length()); buf.get(data); System.out.println("nio size=" + data.length); channel.close(); return data; }
結果。単位は、byteとmsec。
100 | 1,000 | 10,000 | 100,000 | 1,000,000 | 10,000,000 | 100,000,000 | |
---|---|---|---|---|---|---|---|
java.io | 0 | 0 | 1 | 0 | 7 | 58 | 350 |
java.nio(新) | 5 | 1 | 0 | 1 | 4 | 37 | 218 |
java.nio(旧) | 1 | 0 | 0 | 1 | 6 | 67 | 424 |