一、引言:Java I/O 的重要性
无论是桌面软件、服务器后台,还是移动应用,文件读写和数据传输都是核心功能。Java 提供了丰富的 I/O API,从传统的字节流、字符流到现代的 NIO(Non-blocking I/O)框架,都能满足不同场景的需求。
本文将深入解析 Java I/O 的核心机制和实战技巧,涵盖:
- 传统流体系(InputStream/OutputStream,Reader/Writer)
- 文件操作示例
- NIO 基础与实战
- 高效文件复制与缓冲机制
二、Java 传统 I/O:字节流和字符流基础
Java I/O 最早的模型是基于流的概念。数据以流的形式从源头流向目的地。
2.1 字节流与字符流的区别
- 字节流(InputStream/OutputStream):以 8 位字节为单位处理数据,适合所有类型数据,包括二进制文件(图片、音频等)。
- 字符流(Reader/Writer):以 16 位字符为单位,专门处理文本文件,自动处理字符编码。
2.2 读取文件示例 — 字节流
try (FileInputStream fis = new FileInputStream("input.dat")) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
// 处理字节
System.out.println("读取了 " + bytesRead + " 字节");
}
} catch (IOException e) {
e.printStackTrace();
}
2.3 读取文件示例 — 字符流
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("读取行: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
2.4 写入文件示例
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
writer.write("Hello, Java I/O!");
writer.newLine();
writer.write("写入结束");
} catch (IOException e) {
e.printStackTrace();
}
三、缓冲流:提升 I/O 性能的关键
缓冲流通过减少物理读写次数极大提升效率。
3.1 常用缓冲流类
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
3.2 示例:用缓冲流复制文件
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("source.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("dest.jpg"))) {
byte[] buffer = new byte[8192];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
四、Java NIO:现代非阻塞 I/O
Java NIO(New I/O)在 Java 1.4 引入,提供了更高效的 I/O 操作方式。
4.1 NIO 主要组件
组件 | 描述 |
Buffer | 数据容器 |
Channel | 连接实体,读写数据的通道 |
Selector | 多路复用器,实现非阻塞I/O |
4.2 Buffer 基础
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Hello NIO".getBytes());
buffer.flip(); // 切换到读取模式
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
4.3 Channel 操作示例
try (FileChannel inChannel = new FileInputStream("input.txt").getChannel();
FileChannel outChannel = new FileOutputStream("output.txt").getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) != -1) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
4.4 Selector 和非阻塞网络 I/O(简介)
Selector 允许单线程管理多个网络连接,实现高性能服务器。
// 示例略,核心思想是通过 Selector 监听多个 Channel 的事件
五、文件操作常见技巧
5.1 文件读写路径与编码
- 使用
Paths.get()
和Files
操作更便捷(Java 7+)
Path path = Paths.get("test.txt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
5.2 判断文件是否存在、创建文件
if (!Files.exists(path)) {
Files.createFile(path);
}
六、实战:高效复制大文件
结合 NIO 零拷贝技术,实现快速复制。
try (FileChannel source = FileChannel.open(Paths.get("large.iso"), StandardOpenOption.READ);
FileChannel target = FileChannel.open(Paths.get("copy.iso"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
long size = source.size();
long transferred = 0;
while (transferred < size) {
transferred += source.transferTo(transferred, size - transferred, target);
}
} catch (IOException e) {
e.printStackTrace();
}
七、总结与提升
- Java I/O 从传统流到 NIO 都有丰富的 API。
- 了解缓冲流和文件通道能显著提升性能。
- 现代项目推荐使用 NIO 和 Files 工具类。
- 未来可进一步学习异步 I/O(AIO)和内存映射文件。