詳解NIO中FileChannel文件流的簡單使用
前言
在文章NIO 下的 ByteBuffer簡單學習 中, 我們有寫過一個簡單的文件讀取案例, 在案例中有使用到 Buffer 和 Channel, 關于 Buffer 的簡單使用可以看下面兩篇文章
關于 Channel 主要分為以下幾種, 本篇文章是對 FileChannel 的講解:
- FileChannel: 文件通道, 主要用于對文件的讀寫
- DatagramChannel: 數據包通道, 可以發(fā)送和接受 UPD 的數據包
- SocketChannel: 套接字通過, 接收 TCP 數據包的讀寫
- ServerSocketChannel: 服務器套接字通道, 監(jiān)聽新進來的 TCP 連接, 為每一個新連接都創(chuàng)建一個 SocketChannel
FileChannel
注意: FileChannel 只能工作在阻塞模式下
新建
FileChannel 是一個抽象類, 所以不能直接創(chuàng)建對象
public abstract class FileChannel
extends AbstractInterruptibleChannel
implements SeekableByteChannel, GatheringByteChannel,ScatteringByteChannel
{
/**
* Initializes a new instance of this class.
* */
protected FileChannel(){}
創(chuàng)建一個 FileChannel 有以下三種方式:
- 創(chuàng)建一個 FileInputStream 對象, 但是該對象獲取到的 Channel 只能讀取
- 創(chuàng)建一個 FileOutputStream 對象, 但是該對象獲取到的 Channel 只能寫入
- 創(chuàng)建一個 RandomAccessFile 對象, 該對象能否讀寫是根據構造 RandomAccessFile 時設置的讀寫模式設定的
注意: Channel 使用之后必須關閉
不主動 close 并且 未觸發(fā)gc , 那么 連接 和 句柄 將被 一直占用, 如果此時使用的是連接池方式, 將造成連接池中的連接不能及時的被回收問題
在調用 FileInputStream 、 FileOutputStream 和 RandomAccessFile 的 close 方法會間接調用 Channel 的 close 方法
實現文件的讀寫
通過以下代碼可以簡單的通過 FileInputStream 和 FileOutputStream 來實現對文件的讀寫
public static void main(String[] args) {
try(
FileChannel inputChannel = new FileInputStream( name: "test1.txt").getChannel();
FileChannel outputChannel = new FileOutputStream( name: "test2.txt").getChannel()
){
// inputChannel 流讀取到的內容通過 outputChannel 傳輸到指定的地址
inputChannel.transferTo( position: 0,inputChannel.size(),outputChannel);
}catch (Exception e){
e.printstackTrace();
}
}但是這里有個問題, FileChannel 的 transferTo 只能傳輸 2G 以內的數據, 超過 2G 就傳輸不了了,
下面是 FileChannel 的 tarnsferTo 方法, 可以看到他是存在返回值的, 這個返回值就代表著還剩下多少字節(jié)的內容沒有進行傳輸, 所以我們可以使用一個 for 循環(huán)來對當前的代碼進行改進

改進后的代碼如下所示
public static void main(String[] args) {
try(
FileChannel inputChannel = new FileInputStream( name: "test1.txt").getChannel();
FileChannel outputChannel = new FileOutputStream( name: "test2.txt").getChannel()
){
//獲取到 輸入流 的大小
long size = inputChannel.size();
// res 代表剩余多少字節(jié)沒有進行傳輸
for (long res = size;res > 0; ){
//將 inputChannel 流讀取到的內容通過 outputChannel 傳輸到指定的地址
// 效率高,底層會利用作系統(tǒng)的 零拷貝 進行優(yōu)化,但是一次只能傳輸 2G 的數據
// 該方法返回值為 剩余未傳輸的 字節(jié)數
res = inputChannel.transferTo( position: 0,inputChannel.size(), outputChannel);
}
}catch (Exception e){
e.printstackTrace();
}
}本篇文章所有代碼
public static void main(String[] args) {
try(
FileChannel inputChannel = new FileInputStream("test1.txt").getChannel();
FileChannel outputChannel = new FileOutputStream("test2.txt").getChannel()
){
// 獲取到 輸入流 的大小
long size = inputChannel.size();
// res 代表剩余多少字節(jié)沒有進行傳輸
for (long res = size; res > 0; ){
// 將 inputChannel 流讀取到的內容通過 outputChannel 傳輸到指定的地址
// 效率高, 底層會利用操作系統(tǒng)的 零拷貝 進行優(yōu)化, 但是一次只能傳輸 2G 的數據
// 該方法返回值為 剩余未傳輸的 字節(jié)數
res = inputChannel.transferTo(0, inputChannel.size(), outputChannel);
}
}catch (Exception e){
e.printStackTrace();
}
}到此這篇關于詳解NIO中FileChannel文件流的簡單使用的文章就介紹到這了,更多相關FileChannel使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java利用iTextPDF庫實現制作PDF表格模板并填充數據
這篇文章主要為大家詳細介紹了如何通過Java的iTextPDF庫制作一個PDF表格模板并填充數據,文中的示例代碼講解詳細,感興趣的小伙伴快跟隨小編一起學習一下吧2023-12-12
ReentrantReadWriteLock?讀寫鎖分析總結
這篇文章主要介紹了ReentrantReadWriteLock 讀寫鎖分析總結,ReentranReadWriteLock中有兩把鎖,一把讀鎖,一把寫鎖,關于這兩把鎖的介紹,需要的小伙伴可以參考一下2022-05-05

