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