☃️前言
上篇文章讲到 字节流, 发现字节里在搬运文件的时候还是比较耗时的, 比如:
final long l = System.currentTimeMillis(); try( FileInputStream fis = new FileInputStream("D:/消失的爱人2014.BD1080P.特效中英双字.mp4"); FileOutputStream fos = new FileOutputStream("D:/消失的爱人2014.BD1080P.特效中英双字_copy.mp4"); ){ byte[] byteArr = new byte[1024]; int len; while( (len = fis.read(byteArr)) != -1 ){ fos.write(byteArr,0,len); } }catch (IOException e){ System.out.println(e.getMessage()); } System.out.println("耗时(ms)" + (System.currentTimeMillis()-l) );
代码显示, 我们搬运一部电影
搬运这部电影耗时如下:
可以看到, 耗时达到了惊人的 103 秒.
这就是为什么还需要缓冲流的原因:
虽然Java中提供了字节流,但使用缓冲流的主要目的是为了提高I/O操作的效率。缓冲流是字节流的装饰器,它们可以在字节流的基础上添加缓冲功能,从而减少与磁盘或网络的实际交互次数,提高读写效率。
下面是一些缓冲流的优势:
- 减少I/O次数: 缓冲流内部维护了一个缓冲区,数据先被写入缓冲区,当缓冲区满了或者达到一定条件时才会真正写入磁盘或网络。这样,多次连续的小数据写入操作就可以合并成一次大的写入操作,减少了实际的I/O次数,提高了效率。
- 减少系统调用: 直接使用字节流进行I/O操作时,每次读写都会导致系统调用,而系统调用的开销较大。缓冲流通过减少实际的I/O次数,也减少了系统调用的次数,从而提高了程序的性能。
- 提供更方便的API: 缓冲流提供了更方便的读写方法,例如readLine()、read()、write()等,使得对流的操作更加简洁和高效。
在实际开发中,使用缓冲流能够更好地提高程序的性能和效率,特别是在处理大量数据或者频繁进行I/O操作时。
☃️字节缓冲流
- 字节缓冲流:
BufferOutputStream
:缓冲输出流BufferedInputStream
:缓冲输入流
- 构造方法:
- 字节缓冲输出流:
BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:
BufferedInputStream(InputStream in)
- 为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲流仅仅提供缓冲区,不具备读写功能 , 而真正的读写数据还得依靠基本的字节流对象进行操作
❄️❄️案例-搬运电影
我们还是实现搬运电影的一个案例, 不过这次使用 缓冲流.
public static void main(String[] args) { final long l = System.currentTimeMillis(); try( BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/消失的爱人2014.BD1080P.特效中英双字.mp4")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/消失的爱人2014.BD1080P.特效中英双字_copy2.mp4")); ){ byte[] bytes = new byte[1024]; int len; while( (len = bis.read(bytes)) != -1 ){ bos.write(bytes, 0, len); } }catch (IOException e){ System.out.println(e.getMessage()); } System.out.println("耗时(ms)" + (System.currentTimeMillis()-l) ); }
☃️总结
使用缓冲流比直接使用字节流高效的原因主要有以下几点:
- 减少I/O次数: 缓冲流内部维护了一个缓冲区,数据先被写入缓冲区,当缓冲区满了或达到一定条件时才会真正进行写入或读取操作。这样,多次连续的小数据写入或读取操作就可以合并成一次大的操作,减少了实际的I/O次数,提高了效率。相比之下,直接使用字节流每次读写都直接与磁盘或网络交互,频繁的I/O操作会降低效率。
- 减少系统调用: 直接使用字节流进行I/O操作时,每次读写都会导致系统调用,而系统调用的开销较大。缓冲流通过减少实际的I/O次数,也减少了系统调用的次数,从而降低了系统调用的开销,提高了程序的性能。
- 优化数据传输: 缓冲流可以批量地读取或写入数据到缓冲区,然后一次性地进行数据传输,这种批量传输在性能上比逐个字节的传输要高效得多。相比之下,直接使用字节流则可能会导致频繁的小数据传输,效率较低。
- 提供更方便的API: 缓冲流提供了更方便的读写方法,例如read()、write()等,使得对流的操作更加简洁和高效。而且,缓冲流还提供了一些额外的功能,比如readLine()用于按行读取文本文件,这些功能使得使用缓冲流更加便利。
缓冲流在内部数据处理和与外部系统交互的方式上都进行了优化,因此相比直接使用字节流,能够提高程序的性能和效率。