熟练掌握并使用Java的NIO操作

Java的New Input/Output (NIO)库是一种非阻塞I/O操作的集合,旨在提高I/O操作的效率。相比于传统的Java I/O(基于java.io包),NIO提供了更灵活、更强大的I/O处理能力。以下是一篇详细的文章,帮助你彻底熟练掌握并使用Java的NIO操作。

一、Java NIO概述
Java NIO(New I/O)主要包含以下几个核心组件:

Channels(通道):用于数据的读写操作,是NIO的核心组件之一。常见的通道类型有:
FileChannel:用于文件读写。
SocketChannel:用于网络客户端的读写。
ServerSocketChannel:用于网络服务器的读写。
DatagramChannel:用于无连接的UDP通信。
Pipe.SourceChannel 和 Pipe.SinkChannel:用于线程间的管道通信。
Buffers(缓冲区):用于临时存储数据。缓冲区是一个字节容器,并提供了一组方法来操作这些字节。常见的缓冲区类型有:
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
Selectors(选择器):用于管理多个Channel,并可以检测哪些Channel可以进行读、写、连接等I/O操作。
二、Buffers(缓冲区)详解

  1. 缓冲区的创建
    java
    ByteBuffer buffer = ByteBuffer.allocate(1024); // 分配一个容量为1024字节的缓冲区
  2. 缓冲区的操作
    写数据:
    java
    buffer.put((byte) 10);
    buffer.put(new byte[]{1, 2, 3, 4});
    buffer.put(new byte[5], 1, 3); // 从索引1开始,复制3个字节
    切换读写模式:
    在写数据之后,需要切换到读模式:

java
buffer.flip();
读数据:
java
while (buffer.hasRemaining()) {
byte b = buffer.get();
System.out.println(b);
}
重置缓冲区:
java
buffer.clear(); // 准备再次写数据
标记和重置:
java
buffer.mark();
buffer.position(5);
buffer.reset(); // 重置到标记的位置
三、Channels(通道)详解

  1. FileChannel
    java
    RandomAccessFile file = new RandomAccessFile("example.txt", "rw");
    FileChannel fileChannel = file.getChannel();

// 写数据到文件
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Hello NIO".getBytes());
buffer.flip();
fileChannel.write(buffer);

// 读数据从文件
buffer.clear();
fileChannel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
http://yim6.5hai.com/
fileChannel.close();
file.close();
2. SocketChannel 和 ServerSocketChannel
客户端:

java
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost", 8080));

ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Hello Server".getBytes());
buffer.flip();
socketChannel.write(buffer);

buffer.clear();
socketChannel.read(buffer);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}

socketChannel.close();
服务器:

java
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);

while (true) {
SocketChannel socketChannel = serverSocketChannel.accept();
if (socketChannel != null) {
socketChannel.configureBlocking(false);

    ByteBuffer buffer = ByteBuffer.allocate(1024);  
    socketChannel.read(buffer);  
    buffer.flip();  
    while (buffer.hasRemaining()) {  
        System.out.print((char) buffer.get());  
    }  

    buffer.clear();  
    buffer.put("Hello Client".getBytes());  
    buffer.flip();  
    socketChannel.write(buffer);  
    socketChannel.close();  
}  

}
四、Selectors(选择器)详解
选择器允许一个单独的线程管理多个通道(Channel),并且能够知道哪些通道可以进行I/O操作。
http://yim7.5hai.com/
java
Selector selector = Selector.open();

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
selector.select(); // 阻塞直到至少有一个通道准备好

Set<SelectionKey> selectedKeys = selector.selectedKeys();  
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();  

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

    if (key.isAcceptable()) {  
        ServerSocketChannel server = (ServerSocketChannel) key.channel();  
        SocketChannel client = server.accept();  
        client.configureBlocking(false);  
        client.register(selector, SelectionKey.OP_READ);  
    } else if (key.isReadable()) {  
        SocketChannel client = (SocketChannel) key.channel();  
        ByteBuffer buffer = ByteBuffer.allocate(1024);  
        client.read(buffer);  
        buffer.flip();  
        while (buffer.hasRemaining()) {  
            System.out.print((char) buffer.get());  
        }  
        client.close();  
    }  

    keyIterator.remove();  
}  

}
五、总结
Java NIO提供了一种高效、灵活的方式来处理I/O操作。通过理解并使用Buffers、Channels和Selectors,可以编写出高并发、高性能的网络应用程序。掌握NIO的关键在于理解其非阻塞的特性和事件驱动的设计模式。希望这篇文章能帮助你彻底掌握Java的NIO操作。

posted @   神经刀  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示