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

相关推荐
laplace01235 小时前
Java八股—MySQL
java·mysql·oracle
闲人编程6 小时前
Python在网络安全中的应用:编写一个简单的端口扫描器
网络·python·web安全·硬件·端口·codecapsule·扫描器
熙客6 小时前
TiDB:分布式关系型数据库
java·数据库·分布式·tidb
你想考研啊7 小时前
linux安装jdk和tomcat和并自启动
java·linux·tomcat
悟能不能悟9 小时前
java的java.sql.Date和java.util.Date的区别,应该怎么使用
java·开发语言
Mr_Xuhhh9 小时前
GUI自动化测试--自动化测试的意义和应用场景
python·集成测试
2301_764441339 小时前
水星热演化核幔耦合数值模拟
python·算法·数学建模
循环过三天9 小时前
3.4、Python-集合
开发语言·笔记·python·学习·算法
Q_Q51100828510 小时前
python+django/flask的眼科患者随访管理系统 AI智能模型
spring boot·python·django·flask·node.js·php
高山上有一只小老虎10 小时前
java 正则表达式大全
java·正则表达式