天天看点

IO流和NIO流做文件传输时效果比较实例

比较IO流和NIO流做文件传输时的效果。

通过分别对500M\1G\1.5G文件拷贝比较不同方式传输的效率。

方法说明如下:

   test  使用传统IO流FileInputStream对文件进行读写;

   test1 使用NIO流的FileChannel(通道、缓冲池)和FileInputStream(文件流)对文件进行读写;

   test2 使用NIO流的FileChannel(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲池到通道;

   test3 使用NIO流的FileChannel、MappedByteBuffer(通道、内存映射)和RandomAccessFile(随记文件类)对文件进行读写;

   test4 使用NIO流的FileChannel(通道和通道连接方式)对文件进行读写;

   test5 使用NIO流的FileChannel、ByteBuffer(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲 池到缓冲池;

直接上代码:

package com.test;

import java.io.File;
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;

/**
 * 比较IO流和NIO流做文件传输时的效果
 * @author Administrator
 * @remark 通过分别对500M\1G\1.5G文件拷贝比较不同方式传输的效率
 * 方法:
 * test  使用传统IO流FileInputStream对文件进行读写
 * test1 使用NIO流的FileChannel(通道、缓冲池)和FileInputStream(文件流)对文件进行读写
 * test2 使用NIO流的FileChannel(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲池到通道
 * test3 使用NIO流的FileChannel、MappedByteBuffer(通道、内存映射)和RandomAccessFile(随记文件类)对文件进行读写
 * test4 使用NIO流的FileChannel(通道和通道连接方式)对文件进行读写
 * test5 使用NIO流的FileChannel、ByteBuffer(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写,写文件时缓冲池到缓冲池
 */
public class NioTest {

	public static void main(String[] args) throws Exception {
		
		NioTest nt = new NioTest();
		long t=0;
		for (int i = 1; i <= 5; i++) {		
			if(i==5) 
				System.out.print("Test:"+(t+=nt.test(i))/i+"ms  ");
		}
		t=0;
		for (int i = 1; i <= 5; i++) {		
			if(i==5) 
				System.out.print("Test1:"+(t+=nt.test1(i))/i+"ms  ");
		}
		t=0;
		for (int i = 1; i <= 5; i++) {	
			if(i==5) 
				System.out.print("Test2:"+(t+=nt.test2(i))/i+"ms  ");
		}
		t=0;
		for (int i = 1; i <= 5; i++) {		
			if(i==5) 
				System.out.print("Test3:"+(t+=nt.test3(i))/i+"ms  ");
		}
		t=0;
		for (int i = 1; i <= 5; i++) {	
			if(i==5) 	
				System.out.print("Test4:"+(t+=nt.test4(i))/i+"ms  ");
		}
		t=0;
		for (int i = 1; i <= 5; i++) {		
			if(i==5) 
				System.out.println("Test5:"+(t+=nt.test5(i))/i+"ms");
		}
	}

	/**
	 * 使用传统IO流FileInputStream对文件进行读写
	 * @param n
	 * @return
	 * @throws Exception
	 */
	public long test(int n) throws Exception {
		byte[] bbb = new byte[4 * 1024];
		File file=new File("C://Users//Administrator//Desktop//Test//t//0.mp4");
		if(file.exists()) file.deleteOnExit();
		FileInputStream fis = new FileInputStream(
				"C://Users//Administrator//Desktop//Test//123.mp4");
		FileOutputStream fos = new FileOutputStream(
				"C://Users//Administrator//Desktop//Test//t//0.mp4");
		long timeStar = System.currentTimeMillis();// 得到当前的时间
		while (fis.read(bbb) != -1) {
			fos.write(bbb);
		}
		long timeEnd = System.currentTimeMillis();// 得到当前的时间
		long time=timeEnd - timeStar;
		//System.out.println("Test方法第"+n+"次 cost time :" + time + "ms");
		fos.flush();
		fis.close();
		fos.close();
		return time;
	}

	/**
	 * 使用NIO流的FileChannel(通道、缓冲池)和FileInputStream(文件流)对文件进行读写
	 * @param n
	 * @return
	 * @throws Exception
	 */
	public long test1(int n) throws Exception {
		long time=0;
		File file=new File("C://Users//Administrator//Desktop//Test//t//1.mp4");
		if(file.exists()) file.deleteOnExit();
		
		ByteBuffer byteBuf = ByteBuffer.allocate(1024<<4);//16K
		FileInputStream fis = new FileInputStream(
				"C://Users//Administrator//Desktop//Test//123.mp4");
		FileOutputStream fos = new FileOutputStream(
				"C://Users//Administrator//Desktop//Test//t//1.mp4");
		FileChannel ifc = fis.getChannel();
		FileChannel ofc = fos.getChannel();
		long timeStar = System.currentTimeMillis();// 得到当前的时间
		while (ifc.read(byteBuf) != -1) {
			byteBuf.flip();
			while (byteBuf.hasRemaining()) {
				ofc.write(byteBuf);
			}
			byteBuf.clear();
		}
		long timeEnd = System.currentTimeMillis();// 得到当前的时间
		time=timeEnd - timeStar;
		fos.flush();
		ifc.close();
		fis.close();
		ofc.close();
		fos.close();
		return time;
	}

	/**
	 * 使用NIO流的FileChannel(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写
	 * @param n
	 * @return
	 * @throws Exception
	 */
	public long test2(int n) {
		long time=0;
		File file=new File("C://Users//Administrator//Desktop//Test//t//2.mp4");
		if(file.exists()) file.deleteOnExit();
		
		RandomAccessFile outRa =null;
		RandomAccessFile inRa = null;
		FileChannel outFc =null;
		FileChannel inFc = null;
		try {
		
		long timeStar = System.currentTimeMillis();// 得到当前的时间
		ByteBuffer byteBuf = ByteBuffer.allocate(1024<<4);//16K
		outRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//t//2.mp4", "rw");
		inRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//123.mp4", "rw");
		outFc = outRa.getChannel();
		inFc = inRa.getChannel();
		
        // 根据 read返回实际读出的字节数 中止循环
        while(inFc.read(byteBuf) != -1){              
            // 缓冲区翻转用于输出到foc
        	byteBuf.flip();
        	outFc.write(byteBuf);  
            // 清空缓冲区用于下次读取          
        	byteBuf.clear();
        }
        
		long timeEnd = System.currentTimeMillis();
		time=timeEnd - timeStar;
		//System.out.println("Test2方法第"+n+"次 cost time :" + time + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
	            // 安全释放资源
	            if(null!=inFc)
					try {
						inFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outFc)
					try {
						outFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=inRa)
					try {
						inRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outRa)
					try {
						outRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
		}
		return time;
	}

	/**
	 * 使用NIO流的FileChannel、MappedByteBuffer(通道、内存映射)和RandomAccessFile(随记文件类)对文件进行读写
	 * @param n
	 * @return
	 * @throws Exception
	 */
	public long test3(int n) throws Exception {
		long time=0;
		File file=new File("C://Users//Administrator//Desktop//Test//t//3.mp4");
		if(file.exists()) file.deleteOnExit();
		
		long length = 0x8000000; // 128 Mb  
		RandomAccessFile outRa =null;
		RandomAccessFile inRa = null;
		FileChannel outFc =null;
		FileChannel inFc = null;
		try {
		
		long timeStar = System.currentTimeMillis();// 得到当前的时间
		
		outRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//t//3.mp4","rw");
		inRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//123.mp4","rw");
		
		outFc = outRa.getChannel();
		inFc = inRa.getChannel();
		
		MappedByteBuffer mbb = null;
		long num = inFc.size()%length==0?inFc.size()/length:inFc.size()/length+1;
		for (long i = 0; i < num; i++) {
			mbb = inFc.map(FileChannel.MapMode.READ_WRITE, i*length,length);
			outFc.write(mbb);
			outFc.force(true);
			mbb.clear();
		}
        
		long timeEnd = System.currentTimeMillis();
		time=timeEnd - timeStar;
		//System.out.println("Test3方法第"+n+"次 cost time :" + time + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
	            // 安全释放资源
	            if(null!=inFc)
					try {
						inFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outFc)
					try {
						outFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=inRa)
					try {
						inRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outRa)
					try {
						outRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
		}
		return time;
	}
	
	/**
	 * 使用NIO流的FileChannel(通道和通道连接方式)对文件进行读写
	 * @param n
	 * @return
	 * @throws Exception
	 */
	public long test4(int n) throws Exception {
		long time=0;
		File file=new File("C://Users//Administrator//Desktop//Test//t//4.mp4");
		if(file.exists()) file.deleteOnExit();
		
		RandomAccessFile outRa =null;
		RandomAccessFile inRa = null;
		FileChannel outFc =null;
		FileChannel inFc = null;
		try {
		
		long timeStar = System.currentTimeMillis();// 得到当前的时间
		outRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//t//4.mp4","rw");
		inRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//123.mp4","rw");
		outFc = outRa.getChannel();
		inFc = inRa.getChannel();
		outFc.transferFrom(inFc, 0, inFc.size());
		
		long timeEnd = System.currentTimeMillis();
		time=timeEnd - timeStar;
		//System.out.println("Test4方法第"+n+"次 cost time :" + time + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
	            // 安全释放资源
	            if(null!=inFc)
					try {
						inFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outFc)
					try {
						outFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=inRa)
					try {
						inRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outRa)
					try {
						outRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
		}
		return time;
	}
	
	/**
	 * 使用NIO流的FileChannel、ByteBuffer(通道、缓冲池)和RandomAccessFile(随记文件类)对文件进行读写
	 * @param n
	 * @return
	 * @throws Exception
	 */
	public long test5(int n) throws Exception {
		long time=0;
		File file=new File("C://Users//Administrator//Desktop//Test//t//5.mp4");
		if(file.exists()) file.deleteOnExit();
		
		RandomAccessFile outRa =null;
		RandomAccessFile inRa = null;
		FileChannel outFc =null;
		FileChannel inFc = null;
		try {
		
		long timeStar = System.currentTimeMillis();// 得到当前的时间
		
		outRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//t//5.mp4","rw");
		inRa = new RandomAccessFile(
				"C://Users//Administrator//Desktop//Test//123.mp4","rw");
		
		outFc = outRa.getChannel();
		inFc = inRa.getChannel();

		ByteBuffer bb,cc = null;
		long i = 0;   
	    long size = inFc.size()/50;    
	    while(i<inFc.size()&&(inFc.size()-i)>size){   
			bb = inFc.map(FileChannel.MapMode.READ_WRITE, i,size);
			cc = outFc.map(FileChannel.MapMode.READ_WRITE, i,size);
			cc.put(bb);
			i+=size; 
			bb.clear();
			cc.clear();
		}
        
		long timeEnd = System.currentTimeMillis();
		time=timeEnd - timeStar;
		//System.out.println("Test5方法第"+n+"次 cost time :" + time + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
	            // 安全释放资源
	            if(null!=inFc)
					try {
						inFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outFc)
					try {
						outFc.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=inRa)
					try {
						inRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
	            if(null!=outRa)
					try {
						outRa.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
		}
		return time;
	}
}
           

以下是运行传输结束比较:

*************************************500M文件************************************

Test:618ms  Test1:225ms  Test2:1368ms  Test3:3566ms  Test4:160ms  Test5:330ms

Test:561ms  Test1:382ms  Test2:1329ms  Test3:3368ms  Test4:142ms  Test5:312ms

Test:626ms  Test1:236ms  Test2:1436ms  Test3:3448ms  Test4:163ms  Test5:305ms

Test:736ms  Test1:268ms  Test2:1561ms  Test3:6435ms  Test4:161ms  Test5:243ms

*************************************1.13G文件************************************

Test:8439ms  Test1:3665ms  Test2:8330ms  Test3:7419ms  Test4:2381ms  Test5:3557ms

Test:4188ms  Test1:5398ms  Test2:14902ms  Test3:5907ms  Test4:2007ms  Test5:9520ms

Test:2985ms  Test1:8266ms  Test2:4998ms  Test3:7892ms  Test4:2270ms  Test5:10894ms

Test:7416ms  Test1:6306ms  Test2:5537ms  Test3:6759ms  Test4:1930ms  Test5:10058ms

*************************************1.5G文件************************************

Test:7920ms  Test1:3733ms  Test2:5194ms  Test3:6278ms  Test4:1812ms  Test5:797ms

Test:6178ms  Test1:5482ms  Test2:9191ms  Test3:5667ms  Test4:1930ms  Test5:32867ms

Test:2774ms  Test1:4606ms  Test2:4973ms  Test3:6189ms  Test4:1856ms  Test5:750ms

Test:7268ms  Test1:3052ms  Test2:4863ms  Test3:11470ms  Test4:1681ms  Test5:35025ms

最终测试证明,使用NIO流的传输文件效率较高,尤其使用第四种方式(通道到通道的传输)效果更明显。

继续阅读