java.nio 包详解
java.nio
(New I/O)是 Java 1.4 引入的高性能 I/O API,提供了比传统 java.io
更高效的 I/O 操作方式,特别适合处理大量数据和高并发场景。
核心组件
1. 缓冲区(Buffers)
核心类:
-
ByteBuffer
、CharBuffer
、ShortBuffer
、IntBuffer
、LongBuffer
、FloatBuffer
、DoubleBuffer
-
MappedByteBuffer
(内存映射文件缓冲区)
基本用法:
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024); // 堆缓冲区
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024); // 直接缓冲区// 写入数据
buffer.put((byte)1);
buffer.putInt(123);
buffer.putDouble(3.14);// 切换为读模式
buffer.flip();// 读取数据
byte b = buffer.get();
int i = buffer.getInt();
double d = buffer.getDouble();// 清空缓冲区
buffer.clear();
缓冲区状态属性:
-
capacity:缓冲区容量
-
position:当前位置
-
limit:读写限制
-
mark:标记位置
2. 通道(Channels)
核心通道类:
-
FileChannel
:文件通道 -
SocketChannel
、ServerSocketChannel
:TCP 通道 -
DatagramChannel
:UDP 通道 -
Pipe.SinkChannel
、Pipe.SourceChannel
:管道通道
文件通道示例:
// 文件读取
try (FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocate(1024);while (channel.read(buffer) > 0) {buffer.flip();// 处理数据buffer.clear();}
}// 文件写入
try (FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {ByteBuffer buffer = ByteBuffer.wrap("Hello NIO".getBytes());channel.write(buffer);
}
3. 选择器(Selectors)
用于非阻塞 I/O 的多路复用:
Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> iter = selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();if (key.isAcceptable()) {// 处理新连接SocketChannel client = serverChannel.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);// 处理数据}iter.remove();}
}
高级特性
1. 内存映射文件(Memory-Mapped Files)
try (FileChannel channel = FileChannel.open(Paths.get("largefile.dat"), StandardOpenOption.READ)) {MappedByteBuffer mappedBuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());// 直接操作内存映射区域while (mappedBuffer.hasRemaining()) {byte b = mappedBuffer.get();}
}
2. 文件锁定
try (FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.WRITE)) {// 排他锁FileLock lock = channel.lock();try {// 执行写操作channel.write(ByteBuffer.wrap("Data".getBytes()));} finally {lock.release();}// 共享锁(只读)FileLock sharedLock = channel.lock(0, Long.MAX_VALUE, true);
}
3. 分散/聚集 I/O(Scatter/Gather)
// 分散读取
ByteBuffer header = ByteBuffer.allocate(128);
ByteBuffer body = ByteBuffer.allocate(1024);
ByteBuffer[] buffers = {header, body};
channel.read(buffers);// 聚集写入
header.flip();
body.flip();
channel.write(buffers);
4. 文件系统操作
java.nio.file
包(NIO.2,Java 7 引入)提供了更强大的文件系统操作:
Path path = Paths.get("/path/to/file");
Files.createDirectories(path.getParent());
Files.write(path, "content".getBytes(), StandardOpenOption.CREATE);// 遍历目录
try (Stream<Path> stream = Files.list(Paths.get("/tmp"))) {stream.forEach(System.out::println);
}// 文件监控
WatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = Paths.get("/path/to/watch");
dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY);
性能优势
-
非阻塞 I/O:允许单线程管理多个通道
-
内存映射:直接操作文件内存映射,避免系统调用
-
直接缓冲区:减少 JVM 堆与本地内存间的数据拷贝
-
零拷贝:通过
FileChannel.transferTo/transferFrom
实现
与传统 I/O 对比
特性 | java.io | java.nio |
---|---|---|
数据流 | 流式 | 基于缓冲区 |
阻塞模式 | 阻塞 | 可选非阻塞 |
多连接处理 | 每个连接一个线程 | 单线程多路复用 |
性能 | 适合少量连接 | 适合高并发 |
API 复杂度 | 简单 | 较复杂 |
最佳实践
-
大文件处理:优先使用内存映射文件
-
高并发网络:使用 Selector 实现非阻塞 I/O
-
频繁 I/O 操作:使用直接缓冲区减少拷贝
-
资源释放:确保关闭通道和选择器
-
异常处理:妥善处理
IOException
和ClosedChannelException
总结
java.nio
包提供了:
-
基于缓冲区的 I/O 操作
-
非阻塞 I/O 支持
-
内存映射文件功能
-
高效的文件和网络操作
-
更灵活的文件系统接口(NIO.2)
虽然学习曲线比传统 I/O 更陡峭,但在处理高性能 I/O 需求时,NIO 通常是更好的选择。对于简单文件操作,可以结合使用 java.nio.file
包提供的便捷方法。