Java NIO 通道(二)通道基礎
阿新 • • 發佈:2019-02-12
概念
通道是NIO提供的一個全新的東西,提供與I/O服務的直接連線。Channel用於在位元組緩衝區和位於通道的另一側的實體(通常是一個檔案或者套接字)之間進行有效的傳輸資料。
介面定義
public interface Channel extends Closeable {
public boolean isOpen();
public void close() throws IOException;
}
很簡單,只有一個開啟和關閉的方法定義,主要的實現還是實現它的介面。建立通道
Channel廣義的可以分為兩類:
檔案(File)通道:涉及到的類主要是FileChannel。
套接字(socket)通道:涉及到的類主要是SocketChannel,ServerSocketChannel,DatagramChannel。
FileChannel
FileChannel能在File級別或者FileInputStream或者FileOutStream級別上獲取到。
RandomAccessFile raf = new RandomAccessFile("D:/sss","r");
FileChannel fc = raf.getChannel();
FileInputStream fio = new FileInputStream("D:/sss"); FileChannel fc = fio.getChannel();
SocketChannel
SocketChannel sc = SocketChannel.open( );
sc.connect (new InetSocketAddress ("hostaddress", port));
ServerSocketChannel
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(port));
DatagramChannel
DatagramChannel dc = DatagramChannel.open( );
上面都是一些基礎的開啟操作,基於本人沒有實際使用經驗,沒有其他可以分享的體驗了^_^。
通道使用
使用原則
通道的使用基礎是和ByteBuffer打交道,要麼是資料傳輸給ByteBuffer物件或者從ByteBuffer物件獲取資料進行傳輸。
使用方式的判斷
通道分為單向或者雙向。通道可以實現ReadableByteChannel介面用作read功能,或者可以實現WriteableByteChannel介面實現write功能。兩者實現其一定義為單向,實現兩個則定義為雙向通道。
public interface ByteChannel
extends ReadableByteChannel, WritableByteChannel
{
}
ByteChannel實現了兩個介面,它是雙向通道,它本身沒有任何一個方法,只是作為一個類似於中間人的便捷介面。
使用方式
書中給出的經典例子,不是很難理解public static void main(String[] args) throws IOException {
ReadableByteChannel source = Channels.newChannel(System.in);
WritableByteChannel dest = Channels.newChannel(System.out);
channelCopy1(source, dest);
// channelCopy2 (source, dest);
source.close();
dest.close();
}
private static void channelCopy1(ReadableByteChannel src, WritableByteChannel dest)
throws IOException{
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1)
{
// 切換為讀狀態
buffer.flip();
// 不能保證全部寫入
dest.write(buffer);
// 釋放已讀資料的空間,等待資料寫入
buffer.compact();
}
// 退出迴圈的時候,由於呼叫的是compact方法,緩衝區中可能還有資料
// 需要進一步讀取
buffer.flip();
while (buffer.hasRemaining())
{
dest.write(buffer);
}
}
private static void channelCopy2(ReadableByteChannel src, WritableByteChannel dest)
throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1)
{
// 切換為讀狀態
buffer.flip();
// 保證緩衝區的資料全部寫入
while (buffer.hasRemaining())
{
dest.write(buffer);
}
// 清除緩衝區
buffer.clear();
}
// 退出迴圈的時候,由於呼叫的是clear方法,緩衝區中已經沒有資料,不需要進一步處理
}
通道關閉
1.通過close方法關閉通道,可能會出現通道在關閉底層I/O時會阻塞。但是多次呼叫close方法是可以多次呼叫的,不會產生問題。
2.可以通過isopen()方法判斷通道是否開放。關閉的情況下使用會丟擲ClosedChannelException。
3.I/O被中斷時通道會關閉。