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被中断时通道会关闭。

猜你喜欢

转载自blog.csdn.net/qq_32924343/article/details/80596105
今日推荐