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

  • 相关阅读:
    164 Maximum Gap 最大间距
    162 Find Peak Element 寻找峰值
    160 Intersection of Two Linked Lists 相交链表
    155 Min Stack 最小栈
    154 Find Minimum in Rotated Sorted Array II
    153 Find Minimum in Rotated Sorted Array 旋转数组的最小值
    152 Maximum Product Subarray 乘积最大子序列
    151 Reverse Words in a String 翻转字符串里的单词
    bzoj3994: [SDOI2015]约数个数和
    bzoj 4590: [Shoi2015]自动刷题机
  • 原文地址:https://www.cnblogs.com/xieyuan/p/3787294.html
Copyright © 2011-2022 走看看