You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Java中BufferedInputStream设缓冲区大小为1却仅读取文件一次?

为什么BufferedInputStream缓冲区大小为1却只读取一次文件?

要搞懂这个问题,得先理清两个核心逻辑:BufferedInputStream的内部缓冲区作用,以及read(byte[] b)方法的行为。

关键概念拆解

  • 内部缓冲区:你设置的1是BufferedInputStream自己维护的内存块大小,它的作用是减少底层IO的调用次数——每次从底层文件流读取数据时,会尽可能填满这个缓冲区(这里就是每次读1字节)。
  • read(byte[] b)的行为:这个方法的目标是尽可能把你传入的byte数组填满,而不是只读取和缓冲区大小相等的数据。

你的两种场景分析

场景1:byte数组大小为1000,缓冲区大小为1

当你第一次调用b.read(does)时:

  1. BufferedInputStream发现内部缓冲区是空的,就从底层FileInputStream读取1字节(缓冲区大小限制)到自己的缓冲区。
  2. 把这1字节复制到does数组里,此时缓冲区空了,但does还剩999字节的空间。
  3. 重复步骤1和2:再次从底层读1字节到缓冲区,复制到does,直到数组被填满或者文件数据耗尽。
  4. 你的文件只有465字节,所以这一次read(does)就把所有数据都读进了数组,返回值i=465。
  5. 进入while循环处理数据后,再次调用read(does)时,底层流已经没有数据,返回-1,循环结束。所以你看到的x=1,是指read(does)方法只被调用了1次——但底层文件流实际被调用了465次(每次读1字节),只是BufferedInputStream帮你把这些操作合并成了一次数组读取。

场景2:byte数组大小为1,缓冲区大小为1

当你把does改成大小为1的数组时:

  1. 第一次调用b.read(does),BufferedInputStream从底层读1字节到缓冲区,复制到数组后返回i=1。
  2. 处理完数据再次调用b.read(does),此时缓冲区已空,就再从底层读1字节,复制到数组后返回i=1。
  3. 这个过程重复465次,直到文件读完,最后一次调用返回-1,循环结束。所以x=465,也就是read(does)方法被调用了465次。

总结

  • 缓冲区大小决定的是每次从底层流读取多少字节到BufferedInputStream的内部缓存,而不是每次read方法返回的字节数。
  • read(byte[] b)的返回字节数,由传入的数组大小和剩余文件数据量共同决定——它会尽可能填满你的数组,直到文件读完。
  • 如果你想验证底层流的实际读取次数,可以自己写个继承FileInputStream的包装类,重写read()方法并计数,就能看到缓冲区大小为1时,底层read确实被调用了465次。

内容的提问来源于stack exchange,提问作者kaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:32:50