JAVA NIO文件映射、通道、流读写文件示例

来源:互联网 发布:如何进行seo 编辑:程序博客网 时间:2024/05/17 06:04

本例使用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;}@Overridepublic 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;}}

INIOTest.java

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;}


Test.java

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

4 0