天天看點

四種位元組流複制檔案的效率比較

單個位元組讀取後再寫入到流中的方式太慢了,暫且不讨論之(main函數中已經注釋掉了)。

其實通過閱讀bufferedoutputstream的源碼我們可以知道, bufferedoutputstream實際上就是提供了一個數組來緩沖資料,而在方式二中,我們同樣提供了一個數組來緩沖資料,将讀取到的資料先存到數組中。一開始,方式二與方式四用于接收讀取的到的資料的數組長度都是1024,運作之後,确實是用了緩沖輸出流的方法四比較快,這讓我覺得很是奇怪,緩沖輸出流的原理确實使用數組緩存資料,然後積累到一定程度就寫入到流中啊,為什麼同樣的原理緩沖輸出流就是快呢。

後來我意識到,緩沖輸出流中,預設的緩存數組是8k(8192位元組),如果需要複制的資料足夠大,那麼緩沖輸出流每次都是等到數組滿了,也就是有了8K的資料之後,才向流中寫入。而方式二的就隻有1024,每次1k滿了,就向流中寫入資料,這樣跟系統互動的次數自然多了很多。當我把方式二的數組增加到同樣是8192的時候,再運作,方式二的速度反而是比方式四快了。我想原因應該是方式四裡,相當于進行了多次緩沖,這樣就導緻了執行的效率低了一些。

package exercise01;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
 * 	四種位元組流複制檔案的效率比較
	
	可以用System.currentTimeMillis()來擷取系統的時間
 */
public class CopyTest {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		String scName = "1024.rmvb";
		
		File javaSource = new File("D:\\111\\"+scName);
		File javaTargetByte = new File("D:\\222\\Byte"+scName);
		File javaTargetBytes = new File("D:\\222\\Bytes"+scName);
		File javaTargetbuffer = new File("D:\\222\\Buffer"+scName);
		File javaTargetbuffers = new File("D:\\222\\Buffers"+scName);
		//fileByte(javaSource,javaTargetByte);//方式一
		fileBytes(javaSource,javaTargetBytes);//方式二
		//bufferedByte(javaSource,javaTargetbuffer);//方式三
		bufferedBytes(javaSource,javaTargetbuffers);//方式四
	}
	
	//方式一:讀取單個位元組,輸出單個位元組
	public static void fileByte(File source, File target) throws IOException {
		long start = System.currentTimeMillis();
		FileInputStream fis = new FileInputStream(source);
		FileOutputStream fos = new FileOutputStream(target);
		
		int data;
		while((data = fis.read())!= -1) {
			fos.write(data);
		}
		fis.close();
		fos.close();
		long end = System.currentTimeMillis();
		System.out.println("單位元組讀取及輸出,複制一個Java檔案耗時 "+(end - start)+" 毫秒");
	}
	
	//方式二:用數組存儲讀取到的位元組資料,然後寫入
	public static void fileBytes(File source, File target) throws IOException {
		long start = System.currentTimeMillis();
		FileInputStream fis = new FileInputStream(source);
		FileOutputStream fos = new FileOutputStream(target);
		
		byte[] data = new byte[1024];
		int len;
		while((len = fis.read(data))!=-1) {
			fos.write(data, 0, len);
		}
		
		fis.close();
		fos.close();
		long end = System.currentTimeMillis();
		System.out.println("多位元組讀取及輸出,複制一個Java檔案耗時"+(end - start)+"毫秒");
	}
	
	
	//方式三:使用緩沖輸入流按位元組讀取及緩沖輸出流來複制
	public static void bufferedByte(File source, File target) throws IOException {
		long start = System.currentTimeMillis();
		FileInputStream fis = new FileInputStream(source);
		FileOutputStream fos = new FileOutputStream(target);
		BufferedInputStream bis = new BufferedInputStream(fis);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		int data;
		while((data = bis.read())!=-1) {
			bos.write(data);
		}
		bis.close();
		bos.close();
		long end = System.currentTimeMillis();
		System.out.println("使用緩沖輸入流讀取單位元組,緩沖輸出流來複制,耗時"+(end - start)+"毫秒");
	}
	
	//方式四:使用緩沖輸入流及緩沖輸出流來複制
	public static void bufferedBytes(File source, File target) throws IOException {
		long start = System.currentTimeMillis();
		FileInputStream fis = new FileInputStream(source);
		FileOutputStream fos = new FileOutputStream(target);
		BufferedInputStream bis = new BufferedInputStream(fis);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		byte[] data = new byte[1024];
		int len;
		while((len = bis.read(data))!=-1) {
			bos.write(data,0,len);
		}
		bis.close();
		bos.close();
		long end = System.currentTimeMillis();
		System.out.println("使用緩沖輸入流讀取單位元組,緩沖輸出流來複制,耗時"+(end - start)+"毫秒");
	}
	
}