NIO(零拷貝,非零拷貝) 與IO 進行檔案的copy
阿新 • • 發佈:2019-01-04
最近在深入學習java NIO ,把自己的一些體會分享出來,
總結,java NIO效率要高於 java IO,而java nio 零拷貝操作效率要高於 非零拷貝操作,具體程式碼如下:
import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class StreamCopyFile { public static final int SIZE = 10000 ; /** 間接copy * 間接NIO copy 耗時為:4.937s * 間接NIO copy 耗時為:3.971s * @param fis * @param fos * @return */ public static boolean indirectCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException { long l1 = System.currentTimeMillis(); FileChannel srcFileChannel = fis.getChannel(); FileChannel targetFileChannel = fos.getChannel(); //間接獲取ByteBuffer ByteBuffer byteBuffer = ByteBuffer.allocate(SIZE); while(true) { byteBuffer.clear(); int readByte = srcFileChannel.read(byteBuffer); if(readByte == -1) { break; } byteBuffer.flip(); targetFileChannel.write(byteBuffer); } longl2 = System.currentTimeMillis(); System.out.println("間接NIO copy 耗時為:"+(l2-l1)/1000.0 +"s"); return true; }
/** 直接copy * 直接NIO copy 耗時為:3.727s * @param fis * @param fos * @return */ public static boolean directCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException { long l1 = System.currentTimeMillis(); FileChannel srcFileChannel = fis.getChannel(); FileChannel targetFileChannel = fos.getChannel(); //間接獲取ByteBuffer ByteBuffer byteBuffer = ByteBuffer.allocateDirect(SIZE); while(true) { byteBuffer.clear(); int readByte = srcFileChannel.read(byteBuffer); if(readByte == -1) { break; } byteBuffer.flip(); targetFileChannel.write(byteBuffer); } long l2 = System.currentTimeMillis(); System.out.println("直接NIO copy 耗時為:"+(l2-l1)/1000.0 +"s"); return true; }
/** 利用channl 的 transferTo 方法效率最高 * 間接NIO copy 耗時為:4.937s * 間接NIO copy 耗時為:3.971s * @param fis * @param fos * @return */ public static boolean copyFileByTransferTo(FileInputStream fis, FileOutputStream fos) throws IOException { long l1 = System.currentTimeMillis(); FileChannel srcFileChannel = fis.getChannel(); FileChannel targetFileChannel = fos.getChannel(); System.out.println(srcFileChannel.size()); srcFileChannel.transferTo(0,srcFileChannel.size(),targetFileChannel); long l2 = System.currentTimeMillis(); System.out.println("transferTo 耗時為:"+(l2-l1)/1000.0 +"s"); return true; }/** IO 間接copy * io copy 耗時為:5.621s copy result : true * io copy 耗時為:3.727s * @param fis* @param fos* @return*/public static boolean copyFile(FileInputStream fis, FileOutputStream fos) throws IOException { long l1 = System.currentTimeMillis(); byte [] byteArr = new byte[SIZE]; while(true) { int len = fis.read(byteArr); if(len == -1) { break; } fos.write(byteArr); } long l2 = System.currentTimeMillis(); System.out.println("io copy 耗時為:"+(l2-l1)/1000.0 +"s"); return true; }
public static void main(String[] args) throws Exception { // FileInputStream fis = new FileInputStream("D:/temp/解密區塊鏈核心密碼學1.mp4"); FileInputStream fis = new FileInputStream("D:/temp/ebook.rar"); File targetFile1 = new File("d:/temp/test1.rar"); File targetFile2 = new File("d:/temp/test2.mp4"); File targetFile3 = new File("d:/temp/test3.mp4"); if(!targetFile1.exists()) { targetFile1.createNewFile(); } if(!targetFile2.exists()) { targetFile2.createNewFile(); } if(!targetFile3.exists()) { targetFile3.createNewFile(); } FileOutputStream fos1 = new FileOutputStream(targetFile1); FileOutputStream fos2 = new FileOutputStream(targetFile2); FileOutputStream fos3 = new FileOutputStream(targetFile3); // boolean b = copyFile(fis,fos); // boolean b = indirectCopyFile(fis,fos); // boolean b3 = directCopyFile(fis,fos3); // boolean b2 = indirectCopyFile(fis,fos2); // boolean b1 = copyFile(fis,fos1); boolean b1 = indirectCopyFile(fis,fos1); // System.out.println("copy result b1 : "+b1+",b2 : "+b2+",b3 : "+b3); fis.close(); fos1.close(); fos2.close(); fos3.close(); }