1. 程式人生 > 其它 >【NIO】Channel:基本概念及使用

【NIO】Channel:基本概念及使用

技術標籤:IO、RPC框架nio

通道是一個物件,起到連線作用: 讀/寫 ==> Buffer <=> Channel <=> File

  • 寫:我們永遠不會將位元組直接寫入通道中,相反是將資料寫入包含一個或者多個位元組的Buffer。
  • 讀:同樣不會直接從通道中讀取位元組,而是將資料從通道讀入Buffer,再從緩衝區獲取這個位元組。

在NIO 中,根據讀取的file不同,提供了多種通道物件,而所有的通道物件都實現了 Channel 介面。

public interface Channel extends Closeable {
   // 通道是否開啟
   public
boolean isOpen(); // 關閉通道 public void close() throws IOException; }

Channel 的子類非常多,有著一套完善的繼承體系:

我們下面來看看這三個最常見的 Channel 如何使用…

1.FileChannel

Java NIO FileChannel是連線檔案的通道。使用FileChannel,可以從檔案中讀取資料和將資料寫入檔案。使用之前,FileChannel必須被開啟,但是無法直接開啟FileChannel,需要通過InputStreamOutputStreamRandomAccessFile獲取FileChannel

1.使用 NIO讀取資料

任何時候讀取資料,都不是直接從通道讀取,而是從通道讀取到緩衝區。所以使用NIO 讀取資料可以分為下面三個步驟:

  1. 從 FileInputStream 獲取 Channel
  2. 建立 Buffer
  3. 將資料從 Channel 讀取到 Buffer 中
public class FileInputDemo {

    public static void main(String[] args) throws IOException {
        // 1.建立FileInputStream,獲取Channel
        FileInputStream fin = new
FileInputStream("C://test.txt"); FileChannel channel = fin.getChannel(); // 2.建立Buffer ByteBuffer buffer = ByteBuffer.allocate(10); // 3.從Channel讀取資料到Buffer channel.read(buffer); // 注:這裡記住要flip先鎖定,最後要clear解鎖 buffer.flip(); while (buffer.hasRemaining()) { byte b = buffer.get(); System.out.println((char)b); } fin.close(); } }

2.使用 NIO寫入資料

使用 NIO 寫入資料與讀取資料的過程類似,同樣資料不是直接寫入通道,而是寫入緩衝區,可以分為下面三個步驟:

  1. 從 FileInputStream 獲取 Channel
  2. 建立 Buffer
  3. 將資料從Channel 寫入到 Buffer 中
public class FileOutputStreamDemo {

    public static void main(String[] args) throws IOException {
    	// 1.從FileInputStream 獲取 Channel。
        FileOutputStream fout = new FileOutputStream("C://test.txt");
        FileChannel fc = fout.getChannel();
		
        // 2.建立Buffer
        ByteBuffer buffer = ByteBuffer.allocate(10);
		
        // 3.向Buffer寫入資料,然後通過Channel寫入
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte)i);
        }
        
        // 注:這裡記住要flip先鎖定,最後要clear解鎖
        buffer.flip();
        fc.write(buffer);
        buffer.clear();
    }
}

2.ServerSocketChannel

Java NIO中的 ServerSocketChannel是一個可以監聽新進來的TCP連線的通道, 就像標準IO中的ServerSocket一樣。ServerSocketChannel類在java.nio.channels包中。

建立 ServerSocketChannel,並監聽80埠:

ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(80));

3.SocketChannel

SocketChannel 是一種面向流連線只sockets套接字的可選擇通道,用來連線 Socket 套接字,處理網路I/O的通道,基於TCP連線傳輸,實現了可選擇通道,可以被多路複用的。

開啟一個 SocketChannel 並連線某臺伺服器:

SocketChannel sc = SocketChannel.open();
sc.connect(new InetSocketAddress("https://www.test.com", 80));

ServerSocketChannel 和 SocketChannel 繼承了SelectableChannel抽象類。它是"可選擇"通道,也就是 noblocking 通道,它的實現需要 Selector 的支援。關於 Selector 我們放在下一篇去說…