3

我知道将 BufferedInpurStream 包装在 FileInputStream 周围会使读取操作更快,但试图弄清楚如何。我查看了 BufferedInpurStream 的源代码并得到了一些东西。这是我的理解

InputStream in = new BufferedInpurStream(new FileInputStream(filename));
  int byteToRead;
  while((byteToRead = in.read()) != -1)

当我执行 bufferedInpurStream.read() 时,在内部,它将首先一次读取字节块到缓冲区,然后从缓冲区中一个一个地读取每个字节,而不是从文件中读取它(这更昂贵)。一旦那个缓冲区是空的,它将再次用大块字节填充它

而使用 FileInputStream.read() ,从文件中一个一个字节地执行读取操作,这是非常昂贵的

这种理解正确吗?

4

2 回答 2

4

通常,read(byte[] b)(或 read(byte[] b, int off, int len)) 比 read() 更受欢迎,因为它可能具有一些 IO 性能优势。

如果您使用 read(byte[] b),只要您使用相同的缓冲区大小,BufferedInpurStream 就没有实际优势。

void read(InputStream inputStream, int bufferSize) throws IOException
{
    byte[] buffer = new byte[bufferSize];
    int read;
    while ((read = inputStream.read(buffer)) != -1)
    {
       // do some work
    }
}

void read2(InputStream inputStream, int bufferSize) throws IOException
{
    BufferedInputStream bis = new BufferedInputStream(inputStream, bufferSize);
    try
    {
        byte[] buffer = new byte[bufferSize];
        int read;
        while ((read = bis .read(buffer)) != -1)
        {
            // do some work
        }
    }
    finally
    {
        bis.close();
    }
}

尝试阅读和阅读2。您会发现,只要您使用适当的缓冲区大小,Wrapping to BufferedInputStream 并不会提高性能。(实际上它会产生另一个计算成本......)

那么,什么时候需要 BufferedInputStream?这是我的建议:

  • 如果您知道“适当的”缓冲区大小,请直接处理。它产生更短的代码。(例如:文件读取。您可以使用文件大小作为缓冲区大小。)
  • 如果您不知道“适当的”缓冲区大小,或者您必须将 InputStream 传递给另一个库,请将流包装为 BufferedInputStream。您可能会从缓冲中受益。(例如:Web 文件传输。服务器可能不提供内容长度字段。)
于 2013-07-04T16:53:13.630 回答
0

是的。正如您所描述的, BufferedInputStream 大大减少了从流中一次读取一个字节时进行的 IO 调用的数量(因为大多数 read() 调用都命中了缓冲区)。

于 2013-07-04T15:30:12.033 回答