BufferedInputStream 的预读由内部缓冲区自动触发,无需变量控制;它在首次读或缓冲区耗尽时批量加载数据,提升IO效率。
bufferedinputstream 的“预读”不是靠变量控制,而是由其内部缓冲区自动触发的机制。它不依赖用户定义的变量来预读,而是在首次或缓冲区耗尽时,自动从底层流批量加载数据到内存缓冲区,后续读取直接从该缓冲区拿数据——这才是真正提升 io 效率的核心。
简单说:你不需要写代码去“设置预读变量”,关键在于让 read() 调用方式匹配缓冲区行为,并合理配置缓冲区大小。
什么时候预读机制真正起效?
预读只在以下读取模式下被高效利用:
- 频繁调用小粒度读取方法,如
bis.read()(逐字节)、bis.read(byte[])(但每次传很小的数组) - 配合
InputStreamReader+BufferedReader按行解析(如br.readLine()),此时 BufferedInputStream 在底层默默预填缓冲区 - 网络流场景(HTTP 响应、Socket 输入),因单次系统调用延迟高,预读能显著摊薄等待成本
缓冲区大小怎么设才让预读“刚好够用”?
默认 8KB(8192 字节)是通用起点,但最优值取决于你的读取节奏和数据源特性:
- 读大文件(>100MB)或高吞吐网络流:试 32KB–64KB(
new BufferedInputStream(fis, 32 * 1024)) - 中小文件或内存受限环境(如嵌入式):可降到 2KB–4KB,但需实测确认是否仍减少 I/O 次数
- 避免设为 1024 或更小:会导致缓冲区频繁重填,预读收益被抵消
- 别盲目设 1MB:操作系统和磁盘本身已有缓存,过大缓冲区浪费内存且 GC 压力上升
哪些操作会让预读“白忙一场”?
即使加了 BufferedInputStream,以下情况也几乎无收益,甚至拖慢性能:
- 已用
fis.read(buf, 0, buf.length)一次性读 8KB+ —— 底层流本身已在批量读,再包一层纯属冗余 - 总数据量小于 4KB 的小文件 —— 预读还没发挥就结束了
- 反复调用
mark()/reset()且readlimit设得比缓冲区还大:导致 reset 失败,逻辑中断 - 多线程共享同一个 BufferedInputStream 实例:内部状态混乱,预读失效且结果不可预测
一个可靠用法示例
以下写法真正激活预读机制并安全释放资源:
try (FileInputStream fis = new FileInputStream("data.log");
BufferedInputStream bis = new BufferedInputStream(fis, 16 * 1024)) {
int b;
while ((b = bis.read()) != -1) {
// 处理单字节(如协议头解析、文本扫描)
}
} // close() 自动委托关闭 fis,无需额外操作


















