【Netty】NIO 通道 ( Channel ) 组件
文章目錄
- I . 通道 ( Channel ) 概念簡(jiǎn)介
- II . 通道 ( Channel ) 常用類
- III . 常用的 通道 ( Channel ) 之 套接字通道 ( SocketChannel )
- IV . 常用的 通道 ( Channel ) 之 文件通道 ( FileChannel )
- V . 文件通道 ( FileChannel ) 寫出文件 示例代碼
- VI . 文件通道 ( FileChannel ) 讀取文件 示例代碼
- VII . 文件通道 ( FileChannel ) 使用 緩沖區(qū) 拷貝文件 示例代碼
- VIII . 文件通道 ( FileChannel ) 直接使用 通道 拷貝文件 示例代碼
I . 通道 ( Channel ) 概念簡(jiǎn)介
NIO 模型中的 通道 ( Channel ) 組件 :
① NIO 雙向讀寫 : NIO 中的通道 ( Channel ) 是可以雙向讀寫的 , 而 BIO 中的 單一流 ( 輸入流 / 輸出流 ) 只能讀或者只能寫 ;
② NIO 異步讀寫 : NIO 中的通道 ( Channel ) 讀寫時(shí)是異步的 , 全程沒(méi)有阻塞 ;
③ BIO 同步讀寫 : BIO 中的流 , 讀寫時(shí)都需要阻塞等待對(duì)方回應(yīng) ;
④ 通道 ( Channel ) 與 緩沖區(qū) ( Buffer ) : 服務(wù)器中 , 通道 ( Channel ) 與 緩沖區(qū) ( Buffer ) 一一對(duì)應(yīng) , 通道可以讀取緩沖區(qū)中的數(shù)據(jù) , 也可以寫出數(shù)據(jù)到緩沖區(qū)中 , 這也是雙向讀寫 ;
II . 通道 ( Channel ) 常用類
通道 ( Channel ) 常用類 : Channel 在 Java 語(yǔ)言 NIO 中被定義成接口 , 常用的實(shí)現(xiàn)類有如下 :
① FileChannel : 文件通道 , 用于文件的讀寫 ;
② ServerSocketChannel : 服務(wù)器套接字通道 , 其作用與 BIO 中的 ServerSocket 類似 . 用于 TCP 網(wǎng)絡(luò)通信中讀寫數(shù)據(jù) ;
③ SocketChannel : 套接字通道 , 其作用與 BIO 中的 Socket 類似 , 用于 TCP 網(wǎng)絡(luò)通信中讀寫數(shù)據(jù) ;
④ DatagramChannel : 數(shù)據(jù)包通道 , 用于 UDP 網(wǎng)絡(luò)通信中讀寫數(shù)據(jù) ;
III . 常用的 通道 ( Channel ) 之 套接字通道 ( SocketChannel )
常用的 通道 ( Channel ) 之 網(wǎng)絡(luò)套接字通道 ( SocketChannel ) :
① ServerSocketChannel : 在服務(wù)器端 , 維護(hù)一個(gè) ServerSocketChannel 通道 , 客戶端請(qǐng)求服務(wù)器通信時(shí) , 服務(wù)器端線程會(huì)給每個(gè)客戶端創(chuàng)建一個(gè)為該客戶端服務(wù)的 SocketChannel , 之后服務(wù)器與客戶端 , 都通過(guò)該 SocketChannel 進(jìn)行通信 ;
② ServerSocketChannel 和 SocketChannel 都是抽象類 :
- ServerSocketChannel 是抽象類 , 其真實(shí)實(shí)現(xiàn)的類型為 ServerSocketChannelImpl ;
- SocketChannel 是抽象類 , 其真實(shí)類型為 SocketChannelImpl ;
IV . 常用的 通道 ( Channel ) 之 文件通道 ( FileChannel )
常用的 通道 ( Channel ) 之 文件通道 ( FileChannel ) : 主要作用是 讀取 , 寫入 , 映射 , 操作本地文件 ;
FileChannel 常用方法 : 前兩個(gè)是 FileChannel 通道與 緩沖區(qū) 讀寫數(shù)據(jù) , 后兩個(gè)是 FileChannel 與其它 通道 讀寫數(shù)據(jù) ;
- int read(ByteBuffer dst) : 從 FileChannel 通道中讀取數(shù)據(jù) , 放入 dst 字節(jié)緩沖區(qū)中 ;
- int write(ByteBuffer src) : 將 src 緩沖區(qū)中的數(shù)據(jù) , 寫入到 FileChannel 通道中 ;
- long transferFrom(ReadableByteChannel src, long position, long count) : 將字節(jié)數(shù)據(jù)從 src 通道傳輸?shù)奖?FileChannel 通道中 ;
- long transferTo(long position, long count, WritableByteChannel target) : 將字節(jié)數(shù)據(jù)從本 FileChannel 通道傳輸?shù)?target 通道中 ;
V . 文件通道 ( FileChannel ) 寫出文件 示例代碼
1 . 示例需求 : 將 “Hello World” 字符串通過(guò) 文件通道 ( FileChannel ) 寫出到文件中 ;
① 文件通道 ( FileChannel ) 獲取 : NIO 中 , 文件通道 ( FileChannel ) 可以從 文件輸出流 ( FileOutputStream ) 中進(jìn)行獲取 , 其本質(zhì)是通過(guò)文件輸出流 , 向文件中寫出數(shù)據(jù) ;
② 整體流程 : 先將 “Hello World” 字符串寫入 字節(jié)緩沖區(qū) ( ByteBuffer ) , 在將字節(jié)緩沖區(qū) ( ByteBuffer ) 中的數(shù)據(jù) 寫出到 文件通道 ( FileChannel ) 中 , 最后通過(guò) 文件通道 ( FileChannel ) 將數(shù)據(jù)寫出到文件中 ;
2 . 代碼示例 :
package kim.hsl.nio;import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel;public class FileChannelDemo {public static void main(String[] args) {FileOutputStream fos = null;try {String hello = "Hello World";//1 . FileChannel 可以從 FileOutputStream 中獲取fos = new FileOutputStream("file.txt");//2 . 創(chuàng)建 FileChannel , 從 FileOutputStream 中可以獲取到//FileChannel 是抽象類 , 實(shí)際類型是 FileChannelImplFileChannel fc = fos.getChannel();//3 . FileChannel 需要通過(guò) 緩沖區(qū) Buffer 才能與數(shù)據(jù)進(jìn)行讀寫交互ByteBuffer buffer = ByteBuffer.allocate(32);//將數(shù)據(jù)放入緩沖區(qū)中 , flip 方法作用是將 position 位置設(shè)置 0buffer.put(hello.getBytes());buffer.flip();//4 . 將 字節(jié)緩沖區(qū) ByteBuffer 中的數(shù)據(jù)寫入到 文件通道 FileChannel 中fc.write(buffer);} catch (IOException e) {e.printStackTrace();} finally {try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}} }
執(zhí)行結(jié)果 : 在代碼的 src 目錄生成 file.txt 文件 , 內(nèi)容為 Hello World ;
VI . 文件通道 ( FileChannel ) 讀取文件 示例代碼
1 . 示例需求 : 通過(guò) 文件通道 ( FileChannel ) 讀取文件中的數(shù)據(jù) ;
① 文件通道 ( FileChannel ) 獲取 : NIO 中 , 文件通道 ( FileChannel ) 可以從 文件輸入流 ( FileInputStream ) 中進(jìn)行獲取 , 其本質(zhì)是通過(guò)文件輸入流 , 讀取文件中的數(shù)據(jù) ;
② 整體流程 : 先通過(guò)文件輸入流獲取文件通道 ( FileChannel ) , 文件通道 ( FileChannel ) 讀取文件數(shù)據(jù)到 字節(jié)緩沖區(qū) ( ByteBuffer ) 中 , 從 字節(jié)緩沖區(qū) ( ByteBuffer ) 中獲取數(shù)據(jù) , 將該數(shù)據(jù)轉(zhuǎn)為字符串打印出來(lái) ;
2 . 代碼示例 :
package kim.hsl.nio;import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel;public class FileChannelDemo2 {public static void main(String[] args) {FileInputStream fis = null;try {//1 . FileChannel 可以從 FileInputStream 中獲取fis = new FileInputStream("file.txt");//2 . 創(chuàng)建 FileChannel , 從 FileInputStream 中可以獲取到//FileChannel 是抽象類 , 實(shí)際類型是 FileChannelImplFileChannel fc = fis.getChannel();//3 . FileChannel 需要通過(guò) 緩沖區(qū) Buffer 才能與數(shù)據(jù)進(jìn)行讀寫交互ByteBuffer buffer = ByteBuffer.allocate(32);//4 . 將 字節(jié)緩沖區(qū) ByteBuffer 中的數(shù)據(jù)寫入到 文件通道 FileChannel 中int len = fc.read(buffer);//5 . 將數(shù)據(jù)從緩沖區(qū)中取出byte[] stringData = new byte[len];//注意 : ByteBuffer 需要 flip 翻轉(zhuǎn)后才能讀取buffer.flip();buffer.get(stringData);//6 . byte 數(shù)組數(shù)據(jù)轉(zhuǎn)為字符串并打印出來(lái)String fileString = new String(stringData);System.out.println(fileString);} catch (IOException e) {e.printStackTrace();} finally {try {if(fis != null)fis.close();} catch (IOException e) {e.printStackTrace();}}} }執(zhí)行結(jié)果 :
Hello WorldVII . 文件通道 ( FileChannel ) 使用 緩沖區(qū) 拷貝文件 示例代碼
1 . 示例需求 : 通過(guò) 文件通道 ( FileChannel ) 與 字節(jié)緩沖區(qū) ( ByteBuffer ) 進(jìn)行文件拷貝 ;
① 文件通道 ( FileChannel ) 獲取 : NIO 中 , 文件通道 ( FileChannel ) 可以從 文件輸入流 ( FileInputStream ) 中進(jìn)行獲取 , 也可以從 文件輸出流 ( FileOutputStream ) 中獲取 , 其本質(zhì)是通過(guò)文件輸入流 , 讀取文件中的數(shù)據(jù) ;
② 整體流程 :
- 先通過(guò)文件輸入流獲取 輸入文件通道 ( FileChannel ) , 通過(guò)文件輸出流獲取 輸出文件通道 ( FileChannel ) ;
- 文件通道 ( FileChannel ) 讀取文件數(shù)據(jù)到 字節(jié)緩沖區(qū) ( ByteBuffer ) 中
- 輸入文件通道讀取數(shù)文件據(jù)到緩沖區(qū)中 , 輸出文件通道寫出緩沖區(qū)數(shù)據(jù)到文件中 ;
2 . 代碼示例 :
package kim.hsl.nio;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel;public class FileChannelDemo3 {public static void main(String[] args) {FileInputStream fis = null;FileOutputStream fos = null;try {//1 . FileChannel 可以從 FileInputStream 中獲取fis = new FileInputStream("file.txt");fos = new FileOutputStream("file2.txt");//2 . 創(chuàng)建 FileChannel , 從 FileInputStream / FileOutputStream 中可以獲取到//FileChannel 是抽象類 , 實(shí)際類型是 FileChannelImplFileChannel fcIn = fis.getChannel();FileChannel fcOut = fos.getChannel();//3 . FileChannel 需要通過(guò) 緩沖區(qū) Buffer 才能 讀寫文件ByteBuffer buffer = ByteBuffer.allocate(1024);//4 . 讀取 file.txt 文件數(shù)據(jù)到 字節(jié)緩沖區(qū) ByteBuffer , 并寫出到 file2.txt 文件中//循環(huán)退出條件 : 如果 文件 讀取完畢, read 方法會(huì)返回 -1, 代表讀取文件完畢while ( (fcIn.read(buffer)) >= 0 ){//將 ByteBuffer 中的數(shù)據(jù)寫出 file2.txt 文件中//翻轉(zhuǎn)后, 將 position 設(shè)置成 0, 才能開(kāi)始寫出buffer.flip();fcOut.write(buffer);//重置標(biāo)志位, 供下一次循環(huán)使用buffer.clear();}} catch (IOException e) {e.printStackTrace();} finally {try {if(fis != null)fis.close();if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}} }執(zhí)行結(jié)果 :
VIII . 文件通道 ( FileChannel ) 直接使用 通道 拷貝文件 示例代碼
1 . 示例需求 : 兩個(gè) 文件通道 ( FileChannel ) 直接拷貝 ;
① 文件通道 ( FileChannel ) 獲取 : NIO 中 , 文件通道 ( FileChannel ) 可以從 文件輸入流 ( FileInputStream ) 中進(jìn)行獲取 , 也可以從 文件輸出流 ( FileOutputStream ) 中獲取 , 其本質(zhì)是通過(guò)文件輸入流 , 讀取文件中的數(shù)據(jù) ;
② 整體流程 :
- 先通過(guò)文件輸入流獲取 輸入文件通道 ( FileChannel ) , 通過(guò)文件輸出流獲取 輸出文件通道 ( FileChannel ) ;
- 直接將輸入通道數(shù)據(jù)轉(zhuǎn)移到輸出通道 , 即可完成拷貝 ;
2 . 代碼示例 :
package kim.hsl.nio;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel;public class FileChannelDemo4 {public static void main(String[] args) {FileInputStream fis = null;FileOutputStream fos = null;try {//1 . FileChannel 可以從 FileInputStream 中獲取fis = new FileInputStream("file.txt");fos = new FileOutputStream("file3.txt");//2 . 創(chuàng)建 FileChannel , 從 FileInputStream / FileOutputStream 中可以獲取到//FileChannel 是抽象類 , 實(shí)際類型是 FileChannelImplFileChannel fcIn = fis.getChannel();FileChannel fcOut = fos.getChannel();//3 . 直接將 fcIn 通道的內(nèi)容寫出到 fcOut 通道fcOut.transferFrom(fcIn, 0, fcIn.size());} catch (IOException e) {e.printStackTrace();} finally {try {if(fis != null)fis.close();if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}}} }執(zhí)行結(jié)果 :
總結(jié)
以上是生活随笔為你收集整理的【Netty】NIO 通道 ( Channel ) 组件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Netty】NIO 缓冲区 ( Buf
- 下一篇: 【Netty】NIO 缓冲区 ( Buf