无论何种编程语言、何种框架,IO 的本质始终只有一句话:
IO = 数据在不同介质之间的流动
它包含三个核心要素:
数据源(Source) → 数据传输(Stream) → 数据宿(Sink)
从抽象角度看:
所有 IO 技术的演进,本质上都在解决三对矛盾:
| 矛盾维度 | 表现 |
|---|---|
| 速度差异 | CPU 远快于磁盘/网络 |
| 表示差异 | 字节 vs 字符 |
| 同步差异 | 阻塞 vs 非阻塞 |
Java IO 的设计,就是围绕这些矛盾构建的一套抽象体系。
Java IO 并不是一堆 API,而是一套高度工程化的设计体系,其核心哲学包括:
Java IO 将复杂的 IO 世界拆解为清晰的层次:
应用逻辑层
↑
字符处理层(Reader / Writer)
↑
字节处理层(InputStream / OutputStream)
↑
操作系统 IO
Java IO 将功能拆解为:
这正是“节点流 + 处理流”模型的由来。
Java IO 大量使用:
装饰器模式(Decorator Pattern)
而不是通过继承堆积功能。
例如:
new BufferedInputStream(
new FileInputStream("a.txt")
)
这种设计带来:
应用程序只依赖抽象,而不依赖具体实现。
从架构角度看,Java IO 可以抽象为四层:
┌───────────────────────────┐
│ 应用层 API │
└─────────────▲─────────────┘
│
┌─────────────┴─────────────┐
│ 处理流层 │ ← 缓冲、编码、对象化
└─────────────▲─────────────┘
│
┌─────────────┴─────────────┐
│ 节点流层 │ ← 文件、网络、内存
└─────────────▲─────────────┘
│
┌─────────────┴─────────────┐
│ 操作系统 IO │
└───────────────────────────┘
Java IO 的所有类,本质上只解决两个维度问题:
| 维度 | 目的 |
|---|---|
| 数据形态 | 字节 or 字符 |
| 功能职责 | 节点 or 处理 |
这是 Java IO 中最根本的划分:
| 类型 | 抽象 | 面向 |
|---|---|---|
| 字节流 | InputStream / OutputStream | 二进制数据 |
| 字符流 | Reader / Writer | 文本数据 |
代表真实的数据来源或去向:
解决:数据从哪里来、到哪里去
对已有流进行增强:
解决:如何更好地处理数据
可以抽象为一个二维模型:
| 字节流 | 字符流 | |
|---|---|---|
| 节点流 | FileInputStream | FileReader |
| 缓冲处理流 | BufferedInputStream | BufferedReader |
| 转换流 | InputStreamReader | OutputStreamWriter |
| 对象化流 | ObjectInputStream | - |
Java 中的 File 并不是文件本身,而是:
路径的抽象描述
真正代表操作系统文件的是:
FileDescriptor
File 类承载三层含义:
| 层次 | 含义 |
|---|---|
| 路径表示 | 抽象路径 |
| 元数据 | 文件信息 |
| 操作接口 | 创建/删除 |
File → FileInputStream → InputStream
File 只是入口,真正的 IO 行为由流完成。
核心原因:
减少系统调用次数
IO 的最大成本在于:
Buffered 流的价值:
多次小 IO → 一次大 IO
BufferedStream 的本质:
用空间换时间
所有编码问题都可以归结为一句话:
编码与解码使用了不同的字符集
字节流 ←→ 字符流
由两个类承担:
它们是:
字节世界与字符世界的桥梁
统一认知:
字符(Char)
↕ Charset
字节(Byte)
| 模式 | 思想 |
|---|---|
| Reactor | 主动轮询 |
| Proactor | 被动回调 |
经典的服务器模型:
1 + N + M
体现的是:
IO 与业务解耦的思想
对象 → 字节流
两大目的:
| 方式 | 特点 |
|---|---|
| Java 原生 | 稳定但臃肿 |
| Hessian | 跨语言 |
| Kryo | 高性能 |
| JSON | 易读但类型弱 |
Java IO 的发展史:
| 阶段 | 特点 |
|---|---|
| BIO | 阻塞 + 面向流 |
| NIO | 非阻塞 + 面向缓冲区 |
| AIO | 真正异步 |
演进方向始终是:
提高并发能力 + 降低线程成本
| 场景 | 选择 |
|---|---|
| 图片/视频 | 字节流 |
| 文本处理 | 字符流 |
几乎所有生产代码:
都应该使用 Buffered
永远遵循:
明确指定编码