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

相关推荐
零千叶3 小时前
【面试】Java JVM 调优面试手册
java·开发语言·jvm
代码充电宝3 小时前
LeetCode 算法题【简单】290. 单词规律
java·算法·leetcode·职场和发展·哈希表
li3714908903 小时前
nginx报400bad request 请求头过大异常处理
java·运维·nginx
摇滚侠3 小时前
Spring Boot 项目, idea 控制台日志设置彩色
java·spring boot·intellij-idea
新手村领路人3 小时前
opencv gpu cuda python c++版本测试代码
python·opencv·cuda
高洁013 小时前
大模型-高效优化技术全景解析:微调 量化 剪枝 梯度裁剪与蒸馏 下
人工智能·python·深度学习·神经网络·知识图谱
white-persist4 小时前
CSRF 漏洞全解析:从原理到实战
网络·python·安全·web安全·网络安全·系统安全·csrf
Aevget4 小时前
「Java EE开发指南」用MyEclipse开发的EJB开发工具(二)
java·ide·java-ee·eclipse·myeclipse
黄昏晓x4 小时前
C++----多态
java·jvm·c++