詳解NIO中FileChannel文件流的簡單使用
前言
在文章NIO 下的 ByteBuffer簡單學習 中, 我們有寫過一個簡單的文件讀取案例, 在案例中有使用到 Buffer 和 Channel, 關(guān)于 Buffer 的簡單使用可以看下面兩篇文章
關(guān)于 Channel 主要分為以下幾種, 本篇文章是對 FileChannel 的講解:
- FileChannel: 文件通道, 主要用于對文件的讀寫
- DatagramChannel: 數(shù)據(jù)包通道, 可以發(fā)送和接受 UPD 的數(shù)據(jù)包
- SocketChannel: 套接字通過, 接收 TCP 數(shù)據(jù)包的讀寫
- ServerSocketChannel: 服務(wù)器套接字通道, 監(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 對象, 該對象能否讀寫是根據(jù)構(gòu)造 RandomAccessFile 時設(shè)置的讀寫模式設(shè)定的
注意: Channel 使用之后必須關(guān)閉
不主動 close 并且 未觸發(fā)gc , 那么 連接 和 句柄 將被 一直占用, 如果此時使用的是連接池方式, 將造成連接池中的連接不能及時的被回收問題
在調(diào)用 FileInputStream 、 FileOutputStream 和 RandomAccessFile 的 close 方法會間接調(diào)用 Channel 的 close 方法
實現(xiàn)文件的讀寫
通過以下代碼可以簡單的通過 FileInputStream 和 FileOutputStream 來實現(xiàn)對文件的讀寫
public static void main(String[] args) { try( FileChannel inputChannel = new FileInputStream( name: "test1.txt").getChannel(); FileChannel outputChannel = new FileOutputStream( name: "test2.txt").getChannel() ){ // inputChannel 流讀取到的內(nèi)容通過 outputChannel 傳輸?shù)街付ǖ牡刂? inputChannel.transferTo( position: 0,inputChannel.size(),outputChannel); }catch (Exception e){ e.printstackTrace(); } }
但是這里有個問題, FileChannel 的 transferTo 只能傳輸 2G 以內(nèi)的數(shù)據(jù), 超過 2G 就傳輸不了了,
下面是 FileChannel 的 tarnsferTo 方法, 可以看到他是存在返回值的, 這個返回值就代表著還剩下多少字節(jié)的內(nèi)容沒有進行傳輸, 所以我們可以使用一個 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 流讀取到的內(nèi)容通過 outputChannel 傳輸?shù)街付ǖ牡刂? // 效率高,底層會利用作系統(tǒng)的 零拷貝 進行優(yōu)化,但是一次只能傳輸 2G 的數(shù)據(jù) // 該方法返回值為 剩余未傳輸?shù)?字節(jié)數(shù) 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 流讀取到的內(nèi)容通過 outputChannel 傳輸?shù)街付ǖ牡刂? // 效率高, 底層會利用操作系統(tǒng)的 零拷貝 進行優(yōu)化, 但是一次只能傳輸 2G 的數(shù)據(jù) // 該方法返回值為 剩余未傳輸?shù)?字節(jié)數(shù) res = inputChannel.transferTo(0, inputChannel.size(), outputChannel); } }catch (Exception e){ e.printStackTrace(); } }
到此這篇關(guān)于詳解NIO中FileChannel文件流的簡單使用的文章就介紹到這了,更多相關(guān)FileChannel使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis中SqlMapper配置的擴展與應(yīng)用詳細介紹(1)
這篇文章主要介紹了Mybatis中SqlMapper配置的擴展與應(yīng)用(1)的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-11-11關(guān)于ZooKeeper的會話機制Session解讀
這篇文章主要介紹了關(guān)于ZooKeeper的會話機制Session解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02聊聊Spring data jpa @query使用原生SQl,需要注意的坑
這篇文章主要介紹了Spring data jpa@query使用原生SQl,需要注意的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08BigDecimal divide除法除不盡報錯的問題及解決
這篇文章主要介紹了BigDecimal divide除法除不盡報錯的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06