Java IO和NIO是Java中两套不同的输入输出处理体系,前者是传统的IO模型,后者是JDK 1.4引入的新IO模型,两者在设计理念和实现方式上有本质区别。下面我们从多个维度展开对比,同时给出实际代码示例帮助理解。

核心设计理念差异
Java IO基于流(Stream)的概念设计,数据像水流一样按顺序传输,要么输入流要么输出流,不能同时支持读写。而Java NIO基于通道(Channel)和缓冲区(Buffer)设计,通道是双向的,既可以读也可以写,数据通过缓冲区在通道和应用之间传输。
阻塞特性对比
Java IO是阻塞式的,当线程调用read()或者write()方法时,线程会一直阻塞直到数据读完或者写完,期间无法做其他事情。Java NIO支持非阻塞模式,线程发起读写请求后不需要等待操作完成,可以立刻返回去处理其他任务,后续通过选择器(Selector)监听通道的事件状态。
面向操作对象不同
Java IO面向字节流或者字符流操作,比如FileInputStream处理字节流,FileReader处理字符流,操作的是单个的流对象。Java NIO面向通道和缓冲区操作,所有数据先读到缓冲区,再从缓冲区写到通道,通道只是数据传输的通道,不直接操作数据。
典型代码示例对比
Java IO读取文件示例
使用传统的IO流读取文件内容,代码逻辑比较简单,但是是阻塞式的:
import java.io.FileInputStream;
import java.io.IOException;
public class TraditionalIOExample {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
int data;
// 循环读取字节,直到返回-1表示文件结束
while ((data = fis.read()) != -1) {
// 处理读取到的单个字节
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Java NIO读取文件示例
使用NIO的通道和缓冲区读取文件,支持更灵活的操作:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class NIOExample {
public static void main(String[] args) {
FileChannel channel = null;
try {
// 获取文件的通道,设置为只读模式
channel = FileChannel.open(Paths.get("test.txt"), StandardOpenOption.READ);
// 分配一个大小为1024字节的缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 将通道中的数据读到缓冲区
int bytesRead = channel.read(buffer);
while (bytesRead != -1) {
// 切换缓冲区为读模式
buffer.flip();
// 循环读取缓冲区中的数据
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
// 清空缓冲区,准备下一次读取
buffer.clear();
bytesRead = channel.read(buffer);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
适用场景总结
如果是连接数不多、对延迟要求不高的场景,比如简单的文件读写、小规模的客户端连接,使用Java IO更简单,代码编写成本低。如果是高并发、大量连接但需要少量线程处理的场景,比如聊天服务器、即时通讯系统,使用Java NIO的非阻塞特性可以大幅提升系统的吞吐量,减少线程资源的消耗。
| 对比维度 | Java IO | Java NIO |
|---|---|---|
| 核心模型 | 流(Stream) | 通道(Channel)、缓冲区(Buffer) |
| 阻塞特性 | 阻塞 | 支持非阻塞 |
| 操作方向 | 单向(输入流/输出流) | 双向(通道可同时读写) |
| 适用场景 | 低并发、简单IO操作 | 高并发、大量连接场景 |