下面是“Java NIO基础使用示例”的完整攻略。
什么是Java NIO
Java NIO(New IO)是Java SE 1.4中引入的一个新IO API,它支持高速度的I/O,非阻塞式I/O、可扩展的I/O操作和更好的内存管理等特性。相对于传统的Java I/O API,Java NIO更为灵活、高效,因此在高负载的网络应用中得到了广泛的应用。
Java NIO的主要组成部分
Java NIO包含以下核心组成部分:
-
缓冲区(Buffer):缓冲区是用来存放数据的一段连续内存区域,NIO中所有的数据都存储在缓冲区中。
-
通道(Channel):通道用于在缓冲区和数据源(如文件、网络Socket等)之间进行读写操作。通道类似于传统IO中的流,但是通道是双向的,可以进行读写操作,而流只支持单向流动。
-
选择器(Selector):选择器用于监控多个通道的状态,当其中有一个或多个通道准备就绪时,选择器就会返回这些通道,然后可以对这些通道进行读写操作,这样就可以实现单线程处理多个通道的操作。
Java NIO 示例
接下来,我们通过几个示例来演示Java NIO的基本用法。
示例1:使用通道进行文件读写操作
通过以下代码来演示使用通道进行文件读写操作的基本步骤:
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class FileChannelExample {
public static void main(String[] args) throws Exception {
RandomAccessFile file = new RandomAccessFile(new File("input.txt"), "rw");
FileChannel channel = file.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int bytesRead = channel.read(buffer);
while (bytesRead != -1) {
System.out.println("Read " + bytesRead);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear();
bytesRead = channel.read(buffer);
}
file.close();
}
}
代码解释:
-
首先创建一个
RandomAccessFile
对象,指定要读取或写入的文件和操作模式。 -
通过
RandomAccessFile
对象的getChannel()
方法获取文件对应的FileChannel
对象。 -
分配一个缓冲区,用于存放读入的数据。
-
调用
read()
方法读取文件数据,将数据读入缓冲区。 -
调用缓冲区的
flip()
方法,切换为读模式。 -
利用
hasRemaining()
方法判断缓冲区是否还有剩余数据,如果有调用get()
方法获取数据。 -
调用缓冲区的
clear()
方法,清空已经读取的数据,为下一次读取做准备。 -
重复调用
read()
方法直到读取到文件的结尾位置。
示例2:使用选择器进行多路复用
通过以下代码来演示使用选择器进行多路复用的基本步骤:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class SelectorExample {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("localhost", 8080));
channel.register(selector, SelectionKey.OP_CONNECT);
while (true) {
int count = selector.select();
if (count <= 0) {
continue;
}
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
if (key.isConnectable()) {
SocketChannel sc = (SocketChannel) key.channel();
sc.finishConnect();
sc.register(selector, SelectionKey.OP_WRITE);
} else if (key.isWritable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.wrap("Hello World".getBytes());
sc.write(buffer);
buffer.flip();
sc.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.read(buffer);
buffer.flip();
System.out.println(new String(buffer.array()));
sc.close();
}
iterator.remove();
}
}
}
}
代码解释:
-
首先创建一个
Selector
对象。 -
创建一个
SocketChannel
对象,并将其配置为非阻塞模式。 -
调用
connect()
方法连接到服务器,并将该通道注册到选择器中。注册时指定了该通道感兴趣的OP_CONNECT
操作,表示该通道将会连接到服务器。 -
进入无限循环,在循环中调用
select()
方法获取已准备就绪的通道数,如果没有可用的通道,则继续等待。 -
如果有通道已经准备就绪,则调用
selectedKeys()
方法获取已准备就绪的通道的集合。 -
循环遍历集合中的通道,通过判断通道注册时指定的操作类型来确定对应的操作。
-
如果通道已经连接到服务器,则调用
finishConnect()
方法完成连接,并将该通道注册到选择器中。注册时指定了该通道感兴趣的OP_WRITE
操作,表示该通道将会向服务器发送数据。 -
如果通道已经准备好写入数据,则将数据写入通道,然后将该通道注册到选择器中。注册时指定了该通道感兴趣的
OP_READ
操作,表示该通道将会从服务器读取响应数据。 -
如果通道已经准备好读取数据,则读取数据,并将数据打印输出。
-
循环结束之后,关闭通道和选择器。
以上就是Java NIO的两个示例,可以帮助初学者更好地理解Java NIO的基本原理和使用方法。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java nio基础使用示例 - Python技术站