25. Java IO: BufferedInputStream
想要查看此教程的目录请点击:Java IO教程目录贴地址
BufferedInputStream为你的输入流提供了一个缓冲区。缓冲区可以大大的提高IO速度。不是每次从网络或磁盘上读取一个字节,而是每次读取一大块儿内容到内部的缓冲区中。当你从BufferedInputStream读取一个字节时,你其实是从它内部的缓冲区读取的。当缓冲区已经读完,BufferedInputStream会读另一大块的数据到缓冲区中。这通常要比每次读取单字节要快的多,尤其是访问磁盘和大数据量的情况。
BufferedInputStream例子
向InputStream增加一个buffer,只是用BufferedInputStream包装一下:
InputStream input = new BufferedInputStream(
new FileInputStream("c:\\data\\input-file.txt"));
就像你看到的,用BufferedInputStream去给InputStream增加一个buffer是如此简单。BufferedInputStream内部创建了一个字节数组,在InputStream底层调用InputStream.read(byte[])方法来填充数组。
为BufferedInputStream设置buffer大小
你可以设置buffer大小,以便在BufferedInputStream中使用。你可以在构造方法中提供此参数:
int bufferSize = 8 * 1024;
InputStream input = new BufferedInputStream(
new FileInputStream("c:\\data\\input-file.txt"),
bufferSize
);
上面例子中,设置了BufferedInputStream内部缓冲区为 8 KB。buffer大小的最佳设置为 1024 字节的倍数。这在磁盘上等内置缓冲效果最好。
除了给你的输入流增加buffer以外,BufferedInputStream与InputStream完全一样。
BufferedInputStream的最佳buffer大小
你可以做一些实验,去使用不同大小的buffer来确定在你的硬件上哪种buffer尺寸可以提供最高性能。最佳buffer尺寸依赖于你使用的是磁盘还是网络InputStream。
不管是磁盘还是网络流,最佳的buffer大小也可能取决于具体计算机硬件。如果每次读取磁盘内容至少 4KB,那么设置 4KB 以下的buffer大小是不明智的。更好的是设置buffer大小为 4KB 的倍数。实际上设置为 6KB 同样不明智。
即使你的磁盘读取块大小比如是 4KB 每次,使用一个大于这个的缓冲区仍然是一个好主意。磁盘善于按顺序读取数据---这意味着善于读取多个并且他们有先后顺序的块。因此,使用 16KB buffer,或者 64KB(或更大)仍然比 4KB buffer更能给你一个比较好的性能。
还要记住,一些磁盘有兆字节大小的读取缓存。如果你将文件放入内部缓存,您也可以使用一个读操作将所有这些数据都放到BufferedInputStream,用来代替多个读操作。你有可能会担心在读的过程中缓存会有被擦除的风险,从而导致硬盘重新读取该块到缓存中
要找到最佳的BufferedInputStream buffer大小,就要找到磁盘读取的块大小,还有缓存大小,然后让buffer大小为这个的整数倍。你一定要亲自去实验才能找到最佳buffer大小。通过测量不同buffer大小的读取速度来实现这个。
mark() 和 reset()
关于BufferedInputStream一个有趣的地方是它支持从InputStream继承的mark() 和 reset()方法。并不是InputStream所有的子类都支持这两个方法。通常可以调用markSupported()方法去查看是否支持mark() 和 reset()方法,但是BufferedInputStream支持它们