1. 程式人生 > >java檔案普通複製和NIO複製

java檔案普通複製和NIO複製

自從jdk1.4以後就引入了NIO檔案通道的概念,並且是由io的FileinputStream和FileoutputStream獲取

以下程式碼傳入引數

File Copyfile 複製的檔案
File newfile  新檔案

1.傳統IO複製

	public static void traditionCopy(File Copyfile, File newfile) throws Exception {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		byte[] buffer = new byte[2097152];
		try {
			fis = new FileInputStream(Copyfile);
			fos = new FileOutputStream(newfile);
			int read = 0;
			long startTime = System.currentTimeMillis();
			while ((read = fis.read(buffer)) != -1) {
				fos.write(buffer, 0, read);
			}
			long EndTime = System.currentTimeMillis();
			System.out.print("traditionCopy用了毫秒數:");
			System.out.println(EndTime - startTime);
			fos.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fos != null) {
				fos.close();
			}
			if (fis != null) {
				fis.close();
			}
		}
	}

2.NIO複製

	public static void nioCopy(File Copyfile, File newfile) throws Exception {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		FileChannel inFiC = null;
		FileChannel outFoC = null;
		int length = 2097152;
		try {
			fis = new FileInputStream(Copyfile);
			fos = new FileOutputStream(newfile);
			inFiC = fis.getChannel();
			outFoC = fos.getChannel();
			long startTime = System.currentTimeMillis();
			while (inFiC.position() != inFiC.size()) {
				if ((inFiC.size() - inFiC.position()) < length) {
					length = (int) (inFiC.size() - inFiC.position());// 讀取剩下的
				}
				inFiC.transferTo(inFiC.position(), length, outFoC);
				inFiC.position(inFiC.position() + length);
			}
			long EndTime = System.currentTimeMillis();
			System.out.print("nioCopy,用了毫秒總數:");
			System.out.println(EndTime - startTime);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (outFoC != null) {
				outFoC.close();
			}
			if (inFiC != null) {
				inFiC.close();
			}
			if (fos != null) {
				fos.close();
			}
			if (fis != null) {
				fis.close();
			}
		}
	}

3.NIO檔案記憶體映像複製

	public static void nioMappedCopy(File Copyfile, File newfile) throws Exception {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		FileChannel inFiC = null;
		FileChannel outFoC = null;
		int length = 2097152;
		try {
			fis = new FileInputStream(Copyfile);
			fos = new FileOutputStream(newfile);
			inFiC = fis.getChannel();
			outFoC = fos.getChannel();
			long startTime = System.currentTimeMillis();
			while (inFiC.position() != inFiC.size()) {
				if ((inFiC.size() - inFiC.position()) < length) {
					length = (int) (inFiC.size() - inFiC.position());
				}
				MappedByteBuffer inbuffer = inFiC.map(MapMode.READ_ONLY, inFiC.position(), length);
				outFoC.write(inbuffer);
				inFiC.position(inFiC.position() + length);
			}
			long EndTime = System.currentTimeMillis();
			System.out.print("nioMappedCopy用了毫秒數:");
			System.out.println(EndTime - startTime);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (outFoC != null) {
				outFoC.close();
			}
			if (inFiC != null) {
				inFiC.close();
			}
			if (fos != null) {
				fos.close();
			}
			if (fis != null) {
				fis.close();
			}
		}
	}

JAVA NIO中還引入了檔案記憶體對映的概念:現代作業系統大都支援虛擬記憶體對映,這樣,我們可以把核心空間地址與使用者空間的虛擬地址對映到同一個實體地址,這樣,DMA 硬體(只能訪問實體記憶體地址)就可以填充對核心與使用者空間程序同時可見的緩衝區了。 這樣做的好處是,我們在讀取磁碟檔案時,再也不用通過核心緩衝區到使用者程序緩衝區的來回拷貝操作了。作業系統會通過一些頁面排程演算法來將磁碟檔案載入對分頁區進行快取記憶體的實體記憶體。我們就可以通過對映後實體記憶體來讀取磁碟檔案了。


測試mian方法
	public static void main(String[] args) throws Exception {
		File Copyfile = new File("D:\\test\\eclipse-mars.7z");
		File newfilePath = new File("D:\\test\\2\\");
		if (!newfilePath.exists()) {
			newfilePath.mkdirs();
		}
		File traditionNewFile = new File(newfilePath + "/" + "traditionCopy.7z");
		traditionCopy(Copyfile, traditionNewFile);// traditionCopy用了毫秒數:644


		File nioNewFile = new File(newfilePath + "/" + "nioCopy.7z");
		nioCopy(Copyfile, nioNewFile);// nioCopy,複製檔案用了毫秒總數:283


		File nioMappedNewFile = new File(newfilePath + "/" + "nioMappedCopy.7z");
		nioMappedCopy(Copyfile, nioMappedNewFile);//nioMappedCopy用了毫秒數:266


	}

因此,不考慮多執行緒優化,單執行緒檔案複製最快的方法是NIO檔案記憶體映像複製。

PS:終於寫完了。希望以後的自己看到這程式碼要說一句:這破程式碼誰寫的。哈哈。