zoukankan      html  css  js  c++  java
  • JAVA NIO文件映射、通道、流读写文件示例

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

    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

  • 相关阅读:
    Java内存模型
    BigDecimal踩过的大坑
    Java开发小技巧
    多线程同步辅助工具类
    ReentrantLock中的公平锁与非公平锁
    ReentrantLock与synchronized的区别
    推荐一个Java设计模式写的很好的博客
    线程池ThreadPoolExecutor工作原理
    支付系统架构设计转载
    linux 部署脚本
  • 原文地址:https://www.cnblogs.com/xieyuan/p/3787294.html
Copyright © 2011-2022 走看看