一、Java IO体系全景解析(含NIO对比)
1. IO流分类与核心类库
2. 传统IO vs NIO核心差异
特性 | 传统IO | NIO (New I/O) |
---|---|---|
数据单位 | 流(Stream) | 块(Buffer) |
阻塞模式 | 同步阻塞 | 同步非阻塞/异步 |
多路复用 | 不支持 | Selector机制 |
适用场景 | 低并发小文件 | 高并发大文件 |
二、文件读写全场景实战
1. JDK 7+ Files API最佳实践
// 读取小文件(<1GB)
String content = Files.readString(Path.of("data.txt"));
// 写入文件(自动创建目录)
Path dir = Path.of("logs/2023");
Files.createDirectories(dir);
Files.write(dir.resolve("app.log"), data.getBytes());
// 大文件逐行处理(内存优化)
try (Stream<String> lines = Files.lines(Path.of("bigfile.txt"))) {
lines.filter(line -> !line.isEmpty())
.forEach(System.out::println);
}
2. 高效缓冲流使用技巧
// 默认缓冲区8KB,大文件可调整
try (BufferedReader reader = new BufferedReader(
new FileReader("data.txt"), 32768)) { // 32KB缓冲区
String line;
while ((line = reader.readLine()) != null) {
// 处理逻辑
}
}
三、序列化与反序列化深度剖析
1. 默认序列化机制与陷阱
public class User implements Serializable {
private static final long serialVersionUID = 1L; // 必须显式声明
private String name;
private transient String password; // 敏感字段不序列化
// 自定义序列化逻辑
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeObject(EncryptUtil.encrypt(password));
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
this.password = EncryptUtil.decrypt((String) ois.readObject());
}
}
2. 安全序列化替代方案
方案 | 优点 | 缺点 |
---|---|---|
JSON(Jackson) | 跨语言、可读性强 | 性能低于二进制 |
Protobuf | 高性能、强类型 | 需预定义Schema |
Kryo | 极速序列化 | 兼容性较差 |
四、NIO核心组件实战应用
1. Buffer状态机模型
ByteBuffer buffer = ByteBuffer.allocateDirect(1024); // 堆外内存
buffer.put("Hello".getBytes());
buffer.flip(); // 切换读模式
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear(); // 重置缓冲区
2. 多路复用Selector实现高并发
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8080));
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int readyChannels = selector.select();
if (readyChannels == 0) continue;
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
if (key.isAcceptable()) {
// 处理新连接
} else if (key.isReadable()) {
// 读取数据
}
iter.remove();
}
}
五、性能优化与资源管理
1. 内存映射文件(MappedByteBuffer)
try (RandomAccessFile file = new RandomAccessFile("data.bin", "rw")) {
MappedByteBuffer buffer = file.getChannel().map(
FileChannel.MapMode.READ_WRITE, 0, file.length());
buffer.putInt(128); // 直接修改文件内容
}
2. 资源泄露检测与防范
错误模式:
FileInputStream fis = new FileInputStream("file.txt");
// 忘记关闭流 → 文件句柄泄露
正确模式:
try (InputStream is = new FileInputStream("file.txt");
OutputStream os = new FileOutputStream("copy.txt")) {
byte[] buffer = new byte[8192];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} // 自动关闭资源
六、企业级实战案例
1. 实时日志采集系统(NIO实现)
public class LogTailer implements Runnable {
private final Path logPath;
private WatchService watchService;
public void run() {
try {
watchService = FileSystems.getDefault().newWatchService();
logPath.getParent().register(watchService,
StandardWatchEventKinds.ENTRY_MODIFY);
while (!Thread.interrupted()) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
if (event.context().equals(logPath.getFileName())) {
// 读取新增日志内容
readNewLines();
}
}
key.reset();
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
2. 分布式对象传输(Protobuf集成)
// user.proto
syntax = "proto3";
message User {
string name = 1;
int32 age = 2;
repeated string tags = 3;
}
// Java序列化
UserProto.User user = UserProto.User.newBuilder()
.setName("John").setAge(30).addTags("VIP").build();
byte[] data = user.toByteArray();
// 网络传输...
UserProto.User parsedUser = UserProto.User.parseFrom(data);
七、跨语言IO操作对比(Java vs Python vs Go)
功能 | Java | Python | Go |
---|---|---|---|
内存映射文件 | MappedByteBuffer | mmap模块 | syscall.Mmap |
异步IO | CompletableFuture/NIO.2 | asyncio | goroutine + channel |
序列化性能 | 中等(需优化) | 慢(Pickle) | 快(Gob/Protobuf) |
文件监控 | WatchService | watchdog | fsnotify库 |
八、常见陷阱与高频面试题
1. 乱码问题终极解决方案
// 指定字符集读取文件
Files.readString(path, StandardCharsets.UTF_8);
// 转换流处理编码
new InputStreamReader(new FileInputStream("data.txt"), "GBK");
2. 面试题:Java中有几种IO模型?
答案:
- 同步阻塞IO(BIO)
- 同步非阻塞IO(NIO)
- 多路复用IO(Selector)
- 信号驱动IO(Unix特有)
- 异步IO(AIO,Windows实现成熟)