FileChannel類的理解和使用


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/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM