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