java.nio 包详解

java.nio(New I/O)是 Java 1.4 引入的高性能 I/O API,提供了比传统 java.io 更高效的 I/O 操作方式,特别适合处理大量数据和高并发场景。


核心组件

1. 缓冲区(Buffers)

核心类

  • ByteBufferCharBufferShortBufferIntBufferLongBufferFloatBufferDoubleBuffer

  • MappedByteBuffer(内存映射文件缓冲区)

基本用法

java 复制代码
// 创建缓冲区
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:文件通道

  • SocketChannelServerSocketChannel:TCP 通道

  • DatagramChannel:UDP 通道

  • Pipe.SinkChannelPipe.SourceChannel:管道通道

文件通道示例

java 复制代码
// 文件读取
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 的多路复用:

java 复制代码
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)

java 复制代码
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. 文件锁定

java 复制代码
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)

java 复制代码
// 分散读取
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 引入)提供了更强大的文件系统操作:

java 复制代码
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);

性能优势

  1. 非阻塞 I/O:允许单线程管理多个通道

  2. 内存映射:直接操作文件内存映射,避免系统调用

  3. 直接缓冲区:减少 JVM 堆与本地内存间的数据拷贝

  4. 零拷贝 :通过 FileChannel.transferTo/transferFrom 实现

与传统 I/O 对比

特性 java.io java.nio
数据流 流式 基于缓冲区
阻塞模式 阻塞 可选非阻塞
多连接处理 每个连接一个线程 单线程多路复用
性能 适合少量连接 适合高并发
API 复杂度 简单 较复杂

最佳实践

  1. 大文件处理:优先使用内存映射文件

  2. 高并发网络:使用 Selector 实现非阻塞 I/O

  3. 频繁 I/O 操作:使用直接缓冲区减少拷贝

  4. 资源释放:确保关闭通道和选择器

  5. 异常处理 :妥善处理 IOExceptionClosedChannelException


总结

java.nio 包提供了:

  • 基于缓冲区的 I/O 操作

  • 非阻塞 I/O 支持

  • 内存映射文件功能

  • 高效的文件和网络操作

  • 更灵活的文件系统接口(NIO.2)

虽然学习曲线比传统 I/O 更陡峭,但在处理高性能 I/O 需求时,NIO 通常是更好的选择。对于简单文件操作,可以结合使用 java.nio.file 包提供的便捷方法。

相关推荐
测试19983 小时前
软件测试 - 单元测试总结
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
Mahir085 小时前
Spring 循环依赖深度解密:从问题本质到三级缓存源码级解析
java·后端·spring·缓存·面试·循环依赖·三级缓存
曲幽6 小时前
我用了FastApiAdmin后,连夜把踩过的坑都整理出来了
redis·python·postgresql·vue3·fastapi·web·sqlalchemy·admin·fastapiadmin
RyFit7 小时前
SpringAI 常见问题及解决方案大全
java·ai
石山代码7 小时前
C++ 内存分区 堆区
java·开发语言·c++
前端若水7 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
绝知此事7 小时前
【算法突围 01】线性结构与哈希表:后端开发的收纳术
java·数据结构·算法·面试·jdk·散列表
无风听海7 小时前
C# 隐式转换深度解析
java·开发语言·c#
涛声依旧-底层原理研究所8 小时前
残差连接与层归一化通俗易懂的详解
人工智能·python·神经网络·transformer
一只大袋鼠8 小时前
Git 进阶(二):分支管理、暂存栈、远程仓库与多人协作
java·开发语言·git