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 包提供的便捷方法。

相关推荐
m0_6138562929 分钟前
mysql如何利用事务隔离级别解决特定业务冲突_mysql隔离方案选型
jvm·数据库·python
abcnull43 分钟前
用javaparser做精准测试
java·ast·静态代码分析·精准测试·javaparser
叶小鸡1 小时前
Java 篇-项目实战-苍穹外卖-笔记汇总
java·开发语言·笔记
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题】【Java基础篇】第22题:HashMap 和 HashSet 有哪些区别
java·开发语言·哈希算法·散列表·hash
我的xiaodoujiao1 小时前
API 接口自动化测试详细图文教程学习系列16--项目实战演练3
python·学习·测试工具·pytest
juniperhan1 小时前
Flink 系列第21篇:Flink SQL 函数与 UDF 全解读:类型推导、开发要点与 Module 扩展
java·大数据·数据仓库·分布式·sql·flink
ID_180079054731 小时前
Python 实现亚马逊商品详情 API 数据准确性校验(极简可用 + JSON 参考)
java·python·json
c++之路2 小时前
C++23概述
java·c++·c++23
时空系2 小时前
第10篇:继承扩展——面向对象编程进阶 python中文编程
开发语言·python·ai编程
专注API从业者3 小时前
Open Claw 京东商品监控选品实战:一键抓取、实时监控、高效选品
java·服务器·数据库