BufferedInputStream和InputStream采用字节数组传输的优劣
在学习Java的IO流的时候,肯定会有一些小伙伴和我一样有这样的困惑:InputStream自身就可以用字节数组作为缓存区,再整个BufferedInputStream干嘛呢?
针对上述问题,看了下java6的API(唯一的官方中文版????),然后整理了下,再用代码测试,最后总结下结论。
首先上图
从图上就可以看出,BufferedInputStream是InputStream的子类,其实从设计模式上来说,BufferedInputStream采用装饰器模式,增强了InputStream。
那它是不是就比InputStream自身性能更强呢?
其实不然。如果把整个输入输出看做一次事件,如拷贝某个图片,这涉及到输入流到内存,从内存再到输出流,如果采用InputStream和OutputStream共用一个字节数组作为缓冲区,避免了BufferedInputStream和BufferedOutputStream的字节数组的存取,效率反而更高!
我们考虑到应用场景,选取copy这个方式来测试。
分别用图片(1.62M)、压缩文件(388M)和ISO镜像文件(3.87G)
代码:
- BufferedInputStream
public class Demo03Test {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\cn_windows_10_enterprise_x64_dvd_6846957.iso"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\cn_windows_10_enterprise_x64_dvd_6846957.iso"));
byte[] bytes = new byte[1024*8];
int len=0;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.close();
bis.close();
long e = System.currentTimeMillis();
System.out.println("耗时:"+(e-s)+"ms");//25ms 8465ms 132320ms
}
}
InputStream的子类FileInutStream
public class Demo01CopyFiles {
public static void main(String[] args) throws IOException {
long s = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("d:\\cn_windows_10_enterprise_x64_dvd_6846957.iso");
FileOutputStream fos = new FileOutputStream("f:\\cn_windows_10_enterprise_x64_dvd_6846957.iso");
byte[] bytes = new byte[1024*8];
int len=0;
while((len=fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
long e = System.currentTimeMillis();
System.out.println("复制耗时:"+(e-s)+"ms");//37ms 1150ms 130360ms
}
}
-
总结
就如图中所示的,少了中间的转换过程,在大文件传输时,InputStream反而更有优势。 -
后记
更加底层的东西就不太懂了,为了查询这些,也搜集了相关的资料,可能和我的阶段性结论相左,也可以私信,大家探讨。
StackOverFlow的一篇回答,挺精彩的。
其关键论点A BufferedStream hold a small dynamic portion of another stream. ByteArrayInputStream was covered in 2.
,没有太懂,他说Oracle的jdk的tutorial有,链接见下https://docs.oracle.com/javase/tutorial/essential/io/,希望过两年能深入底层,把这些搞懂。