1. 程式人生 > >Java NIO 通道(二)通道基礎

Java NIO 通道(二)通道基礎

概念

通道是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被中斷時通道會關閉。