【NIO】Channel:基本概念及使用
通道是一個物件,起到連線作用: 讀/寫 ==> 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
,需要通過InputStream
,OutputStream
或RandomAccessFile
獲取FileChannel
1.使用 NIO讀取資料
任何時候讀取資料,都不是直接從通道讀取,而是從通道讀取到緩衝區。所以使用NIO 讀取資料可以分為下面三個步驟:
- 從 FileInputStream 獲取 Channel
- 建立 Buffer
- 將資料從 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 寫入資料與讀取資料的過程類似,同樣資料不是直接寫入通道,而是寫入緩衝區,可以分為下面三個步驟:
- 從 FileInputStream 獲取 Channel
- 建立 Buffer
- 將資料從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 我們放在下一篇去說…