本例使用FileChannel和 BufferedInputStream等测试对比。
TestHandler.java 用于实现动态代理,测试运行效率
package com.test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class TestHandler implements InvocationHandler{ private Object obj=null; public TestHandler(Object obj){ this.obj=obj; } public static Object newInstance(Object obj){ Object result=Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new TestHandler(obj)); return result; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result=null; System.out.println("执行中..."); long start=System.currentTimeMillis(); result=method.invoke(obj, args); long end=System.currentTimeMillis(); System.out.println("执行完成,耗时:"+(end-start)); return result; } }
package com.test; import java.io.IOException; public interface INIOTest{ public void copyFileMapped(String oldPath,String newPath) throws IOException; public void copyFileNIO(String oldPath,String newPath) throws IOException; public void copyFile(String oldPath,String newPath) throws IOException; }
package com.test; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class Test implements INIOTest{ public void copyFileMapped(String oldPath,String newPath) throws IOException{ long length=0; RandomAccessFile raf=new RandomAccessFile(oldPath , "r"); FileChannel fcr=raf.getChannel(); length=fcr.size(); //返回要读取文件的映射内存区块 MappedByteBuffer mbb=fcr.map(FileChannel.MapMode.READ_ONLY, 0, length); ByteBuffer buffer=mbb.get(new byte[(int)length]); //要写入的文件 RandomAccessFile raw=new RandomAccessFile(newPath, "rw"); FileChannel fcw=raw.getChannel(); MappedByteBuffer mbbw=fcw.map(FileChannel.MapMode.READ_WRITE, 0, length); for(int i=0;i<length;i++){ mbbw.put(i,buffer.get(i)); } fcw.close(); fcr.close(); raf.close(); raw.close(); /** * MappedByteBuffer是java平台共享内存的实现,把硬盘虚拟为内存, * 主要用于进程间共享数据,所以在进程没有退出前文件是不允许删除的。 * 一个映射的字节缓冲区和文件映射,它代表仍然有效,直到缓冲本身是垃圾收集。 */ raf=null; raw=null; System.gc(); try { //等待垃圾回收 Thread.sleep(100); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } public void copyFileNIO(String oldPath,String newPath) throws IOException{ FileInputStream fis=new FileInputStream(oldPath); FileOutputStream fos=new FileOutputStream(newPath); //获取输入输出通道 FileChannel fcin=fis.getChannel(); FileChannel fout=fos.getChannel(); //创建缓冲区 ByteBuffer buffer=ByteBuffer.allocate(1024); while(true){ //clear方法重设缓冲区,使它可以接受读入的数据 buffer.clear(); int len=fcin.read(buffer); if(len==-1){ break; } //写模式转换成读模式。该限制设置为当前的位置然后位置设置为零。如果标记定义然后丢弃。 //flip方法让缓冲区可以将新读入的数据写入另一个通道 buffer.flip(); fout.write(buffer); } fcin.close(); fout.close(); } public void copyFile(String oldPath,String newPath) throws IOException{ FileInputStream fis=new FileInputStream(oldPath); FileOutputStream fos=new FileOutputStream(newPath); BufferedInputStream bis=new BufferedInputStream(fis); BufferedOutputStream bos=new BufferedOutputStream(fos); byte[] buffer=new byte[1024]; int len=0; while((len=bis.read(buffer))!=-1){ bos.write(buffer,0,buffer.length); } bis.close(); bos.close(); } public static void main(String agrs[]){ INIOTest test1=(INIOTest)TestHandler.newInstance(new Test()); try { test1.copyFileMapped("D:\\upan\\VC++6.0简体中文版.rar","D:\\VC++6.0简体中文版.rar"); test1.copyFileNIO("D:\\upan\\VC++6.0简体中文版.rar","D:\\VC++6.0简体中文版.rar"); test1.copyFile("D:\\upan\\VC++6.0简体中文版.rar","D:\\VC++6.0简体中文版.rar"); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } }
第一个为使用文件映射读写耗时
第二个为文件通道(Channel)读写文件耗时
第三个位BufferedInputStream等耗时
测试多次均是Channel,文件映射读写耗时较稳定,时间也比较短,BufferedInputStream时间也不错,和映射差不多(个人测试的是180M的文件,大文件建议还是使用文件映射可能好点)
特别需要注意的是文件映射无法关闭,MappedByteBuffer是java平台共享内存的实现,把硬盘虚拟为内存,主要用于进程间共享数据,所以在进程没有退出前文件是不允许删除的。也无法访问它。所以这里将它置为null,并等待垃圾回收它。
参考:http://yipsilon.iteye.com/blog/298153
原文:http://blog.csdn.net/tabactivity/article/details/19010969