您的位置:

以nio怎么读为中心

一、NIO的概念

Java NIO(New IO)是一个在JDK1.4中推出的新IO API。它以更接近操作系统底层的方式进行文件操作,相对于传统的IO流,在性能和灵活性方面都有很大的提升。Java NIO主要由以下几个核心部分构成:

  • Channels: 通道
  • Buffers: 缓冲区
  • Selectors: 选择器

通道和缓冲区是NIO数据的核心,选择器则是一个可以用来监视多个通道的对象,是否有事件(如新连接、数据接收)发生。这种方式比旧的阻塞式I/O处理方式更为高效。

二、Channel

Channel,通道是NIO中的一个基本概念。它指的是可以进行IO操作的对象,如文件或网络连接。Channel与传统IO中的流(Stream)有一些重要的区别:

  • 可以既读又写(流必须分别进行读写)
  • 可以异步地进行读写
  • 从Channel中读取的数据总是被读到Buffer中,从Buffer写入到Channel中的数据也总是被写入到Channel中

下面的代码段说明了如何创建一个文件通道并读取其中的内容:

try {
    RandomAccessFile aFile = new RandomAccessFile("file.txt", "rw");
    FileChannel inChannel = aFile.getChannel();

    ByteBuffer buffer = ByteBuffer.allocate(48);
    int bytesRead = inChannel.read(buffer);
    while (bytesRead != -1) {
        System.out.println("Read " + bytesRead);
        buffer.flip();
        while(buffer.hasRemaining()){
            System.out.print((char) buffer.get());
        }
        buffer.clear();
        bytesRead = inChannel.read(buffer);
    }
    aFile.close();
} catch (IOException e) {
    e.printStackTrace();
}

三、Buffer

Buffer是一个用于存储数据的内存块。在NIO库中,所有数据都是用缓冲区处理的。缓冲区实质上是一个数组,并提供了一组方法,方便对数据的存储和检索。

下面的代码段说明了如何创建一个缓冲区并使用put()方法将数据写入缓冲区,并使用flip()方法将Buffer从写模式切换到读模式:

ByteBuffer buf = ByteBuffer.allocate(48);
buf.put("hello world".getBytes());
buf.flip();

while(buf.hasRemaining()){
    System.out.print((char) buf.get());
}

四、Selector

Selector是SelectableChannel对象的多路复用器,用于检查一个或多个通道是否处于准备好状态(如读就绪、写就绪)。

下面的代码段说明了如何使用Selector的代码:

Selector selector = Selector.open();

channel.configureBlocking(false);

SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

while(true) {
    int readyChannels = selector.select();

    if(readyChannels == 0) continue;

    Set selectedKeys = selector.selectedKeys();
    Iterator
    keyIterator = selectedKeys.iterator();

    while(keyIterator.hasNext()) {
        SelectionKey key = keyIterator.next();

        if(key.isAcceptable()) {
            // a connection was accepted by a ServerSocketChannel.

        } else if (key.isConnectable()) {
            // a connection was established with a remote server.

        } else if (key.isReadable()) {
            // a channel is ready for reading

        } else if (key.isWritable()) {
            // a channel is ready for writing
        }

        keyIterator.remove();
    }
}

   
  

五、总结

通过对NIO三个核心部分(通道、缓冲区、选择器)的介绍和示例代码的讲解,可以明确NIO相对于传统IO在性能和灵活性方面的提升。对于Java开发人员,掌握NIO的基础知识,并深入理解其使用方式,将大幅提升开发效率和性能。