BufferedInputStream、BufferedOutputStream的效率问题
BufferedInputStream
BufferedOutputStream
public synchronized void write(byte b[], int off, int len) throws IOException {
if (len >= buf.length) {
// 如果请求长度超过输出缓冲区的大小,刷新输出缓冲区,然后直接写入数据。这样,缓冲流将无害地级联
flushBuffer();
out.write(b, off, len);
return;
}
// 如果请求长度超过缓冲区剩余位置的大小,刷新输出缓冲区
if (len > buf.length - count) {
// 注:方法中也会刷新count为0
flushBuffer();
}
// 将请求数组的请求范围的内容复制到缓冲区的剩余位置上
System.arraycopy(b, off, buf, count, len);
count += len;
}
从源码中可以看到,BufferedOutputStream
在wirte
时,会先判断要写的数据长度是否大于自己的缓冲区,大于缓冲区则直接flush
缓冲区和数据,小于缓冲区则往缓冲区装,直到装不下了再flush
缓冲区。当然,最后的write
还是调用FileOutputStream#write()
方法来实现,只不过用了缓冲区后减少了IO
次数。
而这样做就是否在任何情况下都能提高效率呢?不是的!因为BufferedOutputStream
的缓冲区大小上面是有讲究的。默认的大小是8192,即8k,在BufferedOutputStream
使用默认缓冲区大小的情况下,如果一次读入的数据量(即write()
方法的参数len
)远远小于8K,BufferedOutputStream
比FileOutputStream
是有优势的,因为BufferedOutputStream
明显IO
次数要比FileOutputStream
小,越小则BufferedOutputStream
的优势越明显。经实验证实:
write()
方法的参数len
在4096及以下时,BufferedOutputStream
是有优势的write()
方法的参数len
在4097-8191之间时,FilOutputSteam
反而效率更高,因为在这一段2者的IO
次数差不多,而BufferedOutputStream
要操作2次缓冲区后才能flush
write()
方法的参数len
大于等于8192时,BufferedOutputStream
和FilOutputSteam
效率就基本一样了
深入理解
BufferedInputStream如何缓冲IO以及InputStream中的read(byte[] b) 是否具有缓冲功能