最近在熟悉java的nio功能。nio采用了缓冲区的方式进行文件的读写,这一点更接近于OS执行I/O的方式。写了个新旧I/O复制文件的代码,练练手,顺便验证一下两者读写性能的对比,nio是否真的比普通I/O更快了。
拿来测试复制性能的文件是104MB的视频文件,测试代码如下:
package nio; import java.io.FileInputStream; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; public class NioTest { /** * test * @param args * @throws Exception */ public static void main(String[] args) throws Exception { String infile = "F:\\乱扯逼的西游记.flv"; String outfile = "F:\\a.flv"; String outfile2 = "F:\\a1.flv"; long start = System.currentTimeMillis(); nioCopy(infile, outfile); long end1 = System.currentTimeMillis(); normalCopy(infile, outfile2); long end2 = System.currentTimeMillis(); System.out.println("nio copy lasts: " + (end1 - start)); System.out.println("normal copy lasts: " + (end2 - end1)); } //nio文件复制功能 public static void nioCopy(String infile, String outfile) throws Exception { FileInputStream fin = new FileInputStream(infile); FileOutputStream fout = new FileOutputStream(outfile); FileChannel fcin = fin.getChannel(); FileChannel fcout = fout.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { buffer.clear(); int r = fcin.read(buffer); if (r == -1) { break; } buffer.flip(); fcout.write(buffer); } fcin.close(); fcout.close(); fin.close(); fout.close(); } //普通I/O文件复制功能 public static void normalCopy(String infile, String outfile) throws Exception{ FileInputStream fin = new FileInputStream(infile); FileOutputStream fout = new FileOutputStream(outfile); byte[] block = new byte[1024]; while(fin.read(block) != -1) { fout.write(block); } fin.close(); fout.close(); } }
测试结果如下:
得到这个结果的时候,很震惊!NIO居然更慢,而且慢了400ms。查阅《java编程思想》,书中解释,JDK1.4引入了nio之后,旧的I/O代码也由nio包重新实现过了。但是nio复制文件也不应该慢400ms啊!本来想通过源码的方式排查问题,但是nio读写方法在找实现时,eclipse提示我更换源码包。找普通I/O读写实现的时候,一直追踪到了native方法声明便戛然而止,可能是调用了更底层的C语言的fread,fwrite方法吧。