Java NIO 概览
NIO 与 NIO.2 的核心概念:Buffer/Channel、Path/Files,以及非阻塞与文件 API 的分工。
#concept
#growing
#dev
#java
[!info] related notes
Java NIO 概览
这个概念为什么出现
经典流 API 在部分高并发网络与精细缓冲区控制上吃力。java.nio 引入 Buffer/Channel/Selector 模型;NIO.2(java.nio.file)现代化文件路径与目录操作。多数业务先掌握 Path/Files 与基础 Channel 概念即可。
[!abstract] 一句话理解 NIO 用缓冲区与通道表达 IO;NIO.2 的
Path/Files是现代文件 API;Selector 非阻塞多路复用属于高并发网络进阶,不应当成读写文件的默认姿势。
最小可运行示例
场景:使用 NIO.2 读取配置并复制到工作目录
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class Nio2Config {
public static void main(String[] args) throws Exception {
Path dir = Files.createTempDirectory("svc-");
Path cfg = dir.resolve("app.properties");
Path bak = dir.resolve("app.properties.bak");
try {
Files.writeString(cfg, "port=8080\n", StandardCharsets.UTF_8);
Files.copy(cfg, bak, StandardCopyOption.REPLACE_EXISTING);
System.out.println(Files.readString(bak, StandardCharsets.UTF_8).trim());
System.out.println(Files.size(bak));
} finally {
Files.deleteIfExists(bak);
Files.deleteIfExists(cfg);
Files.deleteIfExists(dir);
}
}
}
建议运行:
javac Nio2Config.java && java Nio2Config
期望输出示例:
port=8080
10
结合场景再看三个关注点
- Path 是文件系统路径抽象,不保证路径存在;语法由 provider/系统决定,不能自动把 Windows 路径解释成 Linux 路径。
Files工具覆盖读写复制,小文件极方便。- Buffer 翻转等细节在网络/高性能场景再深入。
核心概念与准确模型
1. Buffer
- 固定容量容器,有 position/limit/capacity
- flip 把 limit 设为原 position,再将 position 置 0;clear 把 position 置 0、limit 设为 capacity,不擦除数据;compact 把未读数据移到开头,再为追加写入调整位置。
2. Channel
- 双向或单向数据通道
- FileChannel 与 SocketChannel 都是通道,但 FileChannel 不能配置为非阻塞或注册到 Selector;NIO 不等于所有操作都非阻塞。
3. Selector
- Selector 监听注册的可选择通道就绪事件(需非阻塞模式),不是“完成一次完整消息读写”的通知;每次读写仍可能只处理部分数据。
- 现代框架常封装,业务少手写
4. NIO.2 文件
Path,Paths,Files,FileVisitor- WatchService 的支持与事件行为依平台/provider,需处理 OVERFLOW 并重新扫描,不能把通知当作完整可靠的变更日志。
边界情况与反直觉行为
- 直接缓冲区与堆缓冲区分配成本不同。
- read 返回 0 表示本次未读到字节(也可能是缓冲区无剩余空间),不是 EOF;流式通道读到末尾返回 -1。写入也可能不完整。
- 文件锁、内存映射是高级特性,可移植与语义要查清。
常见误区
[!warning] 常见误区:所有 IO 都该手写 Selector 业务系统优先用成熟 HTTP 服务器/框架;先正确后快。
工程实践
- 新的文件操作优先 Path/Files,按边界需要与旧 File API 互转;不必为改 API 名称而全量重写。
- 大文件流式处理;Files.lines/list/walk 返回的流需关闭。Files.copy 不保证原子替换,失败后目标可能只写了一部分。
- 性能热点再考虑零拷贝/映射。
- 与虚拟线程组合时重新评估阻塞模型(版本相关)。
本节总结
- NIO=Buffer/Channel 思维
- NIO.2=现代文件 API
- 非阻塞网络是进阶专项
自测题
Path与File老 API 如何选?- Buffer 的 limit 表示什么直觉?
参考答案
- 新代码用 Path/Files。
- 当前可读/写的边界位置(与 position 配合)。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| NIO.2 File I/O | 教程 | Path/Files |
| java.nio package | API | Buffer/Channel |