BufferedInputStream 的核心作用是减少底层 I/O 调用次数,通过为原始输入流添加内存缓冲(默认8192字节)提升读取性能,尤其适用于顺序读中等以上文件、网络流读取及mark/reset回溯场景;慎用于极小文件、需精确读边界或已用NIO的情况;缓冲区大小应依场景调整,不宜超过64KB;注意close()连锁关闭、mark/reset语义、非线程安全及异常需显式处理。

BufferedInputStream 的核心作用:减少底层 I/O 调用次数
它本身不读文件,只是给 FileInputStream、ByteArrayInputStream 等原始输入流“套一层缓冲”,让每次 read() 大概率从内存拿数据,而不是每次都去磁盘或网络触发系统调用。本质是用少量内存(默认 8192 字节)换显著的性能提升——尤其在频繁读小块数据时,I/O 次数可能下降一个数量级。
什么时候必须用?什么时候反而拖后腿?
必须用的场景:
- 顺序读取中等以上大小的文件(比如 >100KB)
- 从网络流(如 HttpURLConnection.getInputStream())读响应体
- 配合 mark()/reset() 做回溯解析(如解析自定义协议头)
慎用或不用的场景:
- 读极小文件(如几字节的配置标志),缓冲开销反而高于收益
- 需要精确控制每次读取边界(如某些二进制协议解析),缓冲区会“预读”破坏边界语义
- 已经在用 NIO 的 FileChannel + ByteBuffer,再套 BufferedInputStream 属于重复缓冲
缓冲区大小怎么设?别迷信“越大越好”
默认 8192 是通用平衡点,但实际应按场景微调:
- new BufferedInputStream(in, 4096):内存受限环境(如嵌入式 Java)、或读大量超小文件(平均
- new BufferedInputStream(in, 16384):连续读大文件(>10MB)、SSD 或高速网络下追求吞吐
- 不建议超过 64KB:JVM 堆碎片风险上升,且多数 OS 文件系统页缓存已是 4KB,过大的 Java 缓冲区边际收益极低
注意:缓冲区大小只影响内部 buf[] 数组容量,不影响 read(byte[] b) 的参数长度
常见坑:close()、mark/reset 和线程安全
close() 会自动关闭底层流,但若你手动关了 FileInputStream 再关 BufferedInputStream,会抛 IOException;mark(int readlimit) 的 readlimit 不是缓冲区大小,而是“标记后最多能读多少字节才不失效”,若超过,reset() 会失败;BufferedInputStream 不是线程安全的——多个线程共用同一个实例读,pos/count 等字段会竞争,结果不可预测;
最后一点容易被忽略:缓冲流对异常处理没特殊逻辑,IOException 仍需显式捕获,且 try-with-resources 中务必确保最外层流(即 BufferedInputStream)在 finally 块或资源声明中被关闭。










