一、Java IO概述
Java IO(Input/Output) 是Java处理输入输出的核心API,涵盖文件操作、网络通信等场景。其发展分为三个阶段:
- 传统IO (java.io):基于流模型,阻塞式处理
- NIO (java.nio):New IO,支持非阻塞和缓冲通道
- NIO2 (Java7+):增强异步文件操作
二、核心类与设计模式
1. 四大基类
类类型 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
2. 装饰器模式应用
通过组合增强流的功能:
// 示例:缓冲流加速读取
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
三、字节流 vs 字符流
对比项 | 字节流 | 字符流 |
---|---|---|
处理单位 | 1字节 (8bit) | Unicode字符 (2字节) |
典型场景 | 图片、视频等二进制文件 | 文本文件 |
编码处理 | 不自动处理编码 | 自动处理字符编码转换 |
字符流正确用法示例:
// 明确指定字符编码
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("file.txt"), StandardCharsets.UTF_8)) {
// 读取操作
}
四、文件操作大全
1. 传统文件操作
// 创建文件对象
File file = new File("data.txt");
// 判断文件属性
if (file.exists() && file.isFile()) {
System.out.println("文件大小: " + file.length() + " bytes");
}
2. NIO2新特性(Java7+)
Path path = Paths.get("data.txt");
// 一次性读取所有行
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// 遍历目录
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get("."))) {
stream.forEach(System.out::println);
}
五、NIO核心三剑客
1. Buffer缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 写模式
buffer.put("Hello".getBytes());
// 切换读模式
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
2. Channel通道
try (FileChannel channel = FileChannel.open(Paths.get("data.txt"),
StandardOpenOption.READ)) {
ByteBuffer buf = ByteBuffer.allocate(1024);
while (channel.read(buf) > 0) {
buf.flip();
// 处理数据
buf.clear();
}
}
3. Selector多路复用
Selector selector = Selector.open();
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
while (true) {
int readyChannels = selector.select();
if (readyChannels == 0) continue;
Set<SelectionKey> keys = selector.selectedKeys();
// 处理IO事件
}
六、性能优化实践
- 缓冲流选择:BufferedInputStream提升读取效率
- 内存映射文件:处理大文件时使用MappedByteBuffer
- 通道传输:FileChannel.transferTo()实现零拷贝
七、常见问题解答
Q:什么时候用NIO?
- 需要处理成千上万连接时(如聊天服务器)
- 要求低延迟和高吞吐量的场景
- 需要非阻塞IO操作时
Q:序列化注意事项
class User implements Serializable {
private static final long serialVersionUID = 1L; // 显式声明版本号
private transient String password; // 敏感字段不序列化
}
八、总结与资源推荐
- 传统IO:适合简单同步操作
- NIO:适合高并发网络应用
- NIO2:简化文件操作的最佳选择