BufferedInputStream是典型的装饰器模式实现,它不改变原始InputStream接口,而是包装已有流(如FileInputStream)并透明添加缓冲能力,支持mark/reset、减少I/O调用次数,并可与其他装饰器叠加。

BufferedInputStream 是典型的装饰器模式实现
它不改变原始 InputStream 的行为接口,而是把一个已有的输入流(比如 FileInputStream 或 ByteArrayInputStream)包装起来,在其外部增加缓冲能力。整个过程对调用方透明:你依然调用 read()、mark()、reset() 这些方法,但内部执行逻辑已经不同——数据不再每次直接来自磁盘或网络,而是优先从内存缓冲区取。
缓冲区如何减少底层 I/O 调用次数
没有缓冲时,每调用一次 read(),就触发一次系统调用去读一个字节,开销极大。BufferedInputStream 改变了这个节奏:
- 首次 read() 会触发 fill() 方法,一次性从底层流读取默认 8192 字节(或自定义大小)到内部字节数组
- 后续多次 read() 都从该数组中按位置取出字节,完全避开系统调用
- 当数组读完(pos 达到末尾),才再次调用 fill() 加载下一批数据
这相当于把“1000 次单字节读”压缩成“约 2 次 8KB 批量读”,I/O 次数下降两个数量级。
缓冲区大小不是越大越好,需匹配使用场景
默认 8KB 是通用折中值,但实际效果取决于你的数据访问模式:
- 读取超大文件且顺序扫描:可设为 64KB 或 128KB,进一步摊薄 fill() 调用频率
- 内存受限环境(如嵌入式):可降到 1KB~4KB,避免浪费
- 随机读 + mark/reset 频繁:过大的缓冲区可能让 markpos 到 pos 距离拉太远,reset 时需重读更多数据
关键不是盲目调大,而是观察真实 I/O 统计(如 Linux 的 iostat)和应用吞吐量变化。
装饰器带来的额外能力不只是提速
BufferedInputStream 在增强性能的同时,还补全了原始流缺失的语义支持:
- 支持 mark()/reset():原始 FileInputStream 默认不支持标记重读,BufferedInputStream 自己维护 markpos 和 pos 偏移,实现“回退”能力
- 统一异常处理边界:所有异常仍沿原始流抛出,但缓冲层可做预判(如提前发现 EOF)
- 可叠加其他装饰器:比如再套一层 DataInputStream 读基本类型,结构清晰、职责分明
这种能力扩展不侵入原始流代码,正体现了装饰器“动态附加职责”的本质。

















