FileChannel類的理解和使用(java.nio.channels.FileChannel)
知識點:
1、FileChannel類及方法理解;
2、普通輸入輸出流復制文件;
3、FileChannel復制文件;
4、新名詞記錄:{MappedByteBuffer:文件映射在內存的直接換成字節數據;FileLock:代表文件的鎖;ByteBuffer:緩存對象}
概述
對於文件的復制,平時我們都是使用輸入輸出流進行操作,利用源文件創建出一個輸入流,然后利用目標文件創建出一個輸出流,最后將輸入流的數據讀取寫入到輸出流中。這樣也是可以進行操作的。但是利用fileChannel是很有用的一個方式。它能直接連接輸入輸出流的文件通道,將數據直接寫入到目標文件中去。而且效率更高。
FileChannel類
FileChannel是一個用讀寫,映射和操作一個文件的通道。出了讀寫操作之外,還有裁剪特定大小文件truncate(),強制在內存中的數據刷新到硬盤中去force(),對通道上鎖lock()等功能。
他們的使用分別如下面代碼:
ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //讀取1024字節內容到byteBuffer鍾 fileChannelInput.read(byteBuffer);
解釋:上面代碼首先創建一個1024大小的緩沖對象,然后在輸入通道中讀取1024大小數據,放入到緩沖對象中。
byteBuffer.clear(); byteBuffer.put("需要寫入的數據".getBytes()); //類似於flush()函數功能,將buffer里面的數據刷新出去 byteBuffer.flip(); //檢查是否還有數據未寫入 while (byteBuffer.hasRemaining()) fileChannelOutput.write(byteBuffer);
解釋:上面的代碼是將一段字符串寫入到輸出文件通道中,因為寫入的時候並不保證能一次性寫入到文件中,所以需要進行判斷是否全部寫入,如果沒有需要再次調用寫入函數操作
//獲取文件通道位置 fileChannelInput.position(); fileChannelInput.size(); //截取內容 fileChannelInput.truncate(1024); //強制刷新數據到硬盤 fileChannelInput.force(true);
解釋:上面的代碼是獲取文件通道的位置和大小。truncate()方法是截取1024大小的數據,指定長度后面的部分將被刪除。以及將數據強制刷新到硬盤中,因為系統會將數據先保存在內存中,不保證數據會立即寫入到硬盤中,所以有這個需求,就可以直接強制數據寫入內存中。
使用
說那么多可能沒用,我們還是直接來看看分別使用兩種方法進行文件復制的對比。
首先是普通的輸入輸出流進行復制文件:
/** * 普通的文件復制方法 * * @param fromFile 源文件 * @param toFile 目標文件 * @throws FileNotFoundException 未找到文件異常 */ public void fileCopyNormal(File fromFile, File toFile) throws FileNotFoundException { InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = new BufferedInputStream(new FileInputStream(fromFile)); outputStream = new BufferedOutputStream(new FileOutputStream(toFile)); byte[] bytes = new byte[1024]; int i; //讀取到輸入流數據,然后寫入到輸出流中去,實現復制 while ((i = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, i); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) inputStream.close(); if (outputStream != null) outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
解釋:在上面的代碼中,傳入源文件和目標文件兩個參數,然后根據兩個文件,分別出具輸入輸出流,然后將輸入流的數據讀取,並且寫入輸出流中,就完成了文件的復制操作。
下面再看一下利用fileChannel進行文件的復制操作。
/** * 用filechannel進行文件復制 * * @param fromFile 源文件 * @param toFile 目標文件 */ public void fileCopyWithFileChannel(File fromFile, File toFile) { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; FileChannel fileChannelInput = null; FileChannel fileChannelOutput = null; try { fileInputStream = new FileInputStream(fromFile); fileOutputStream = new FileOutputStream(toFile); //得到fileInputStream的文件通道 fileChannelInput = fileInputStream.getChannel(); //得到fileOutputStream的文件通道 fileChannelOutput = fileOutputStream.getChannel(); //將fileChannelInput通道的數據,寫入到fileChannelOutput通道 fileChannelInput.transferTo(0, fileChannelInput.size(), fileChannelOutput); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileInputStream != null) fileInputStream.close(); if (fileChannelInput != null) fileChannelInput.close(); if (fileOutputStream != null) fileOutputStream.close(); if (fileChannelOutput != null) fileChannelOutput.close(); } catch (IOException e) { e.printStackTrace(); } } }
解釋:上面代碼中,也是先分別創建了兩個文件的輸入輸出流,然后在分別獲取到兩個文件的文件通道,然后將源文件的文件通道直接和目標文件的文件通道進行連接,直接將數據寫入到目標文件中區。不需要進行分別的讀取和寫入操作了。
運行代碼之后,復制一個文件,對比兩種復制方法,發現利用filechannel使用的時間比普通的讀取輸入時間縮短了將近一半。尤其是在進行大文件復制的時候,filechannel顯得更加有優勢。這里就不貼出圖片了。見諒!
總結
這里我們了解了FileChannel類,知道了它所具有的特點和功能,那么我們就可以好好的使用它了。尤其是在我們復制文件的時候,可以更好的利用這個類,可以提高效率,也可以防止出現oom等其它情況。
以上就是所有內容,如有任何問題,請及時留言與我聯系。(博客:http://www.cnblogs.com/yjd_hycf_space/)