Java中IO流的BufferedOutputStream和FileOutputStream对比

 更新时间:2023年07月25日 09:16:07   作者:java叶新东老师  
这篇文章主要介绍了Java中IO流的BufferedOutputStream和FileOutputStream对比,不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以在读写的字节比较少的情况下,效率比较低,需要的朋友可以参考下

FilteOutputStream

不带缓冲的操作(FilteOutputStream类和FilteInputStream类),每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以在读写的字节比较少的情况下,效率比较低;

FileOutputStream fileOutputStream = new FileOutputStream("D:\\1.txt");

BufferedOutputStream

BufferedOutputStream是带缓冲区的输出流,不管是BufferedOutputStream还是BufferedInputStream里面都自带了默认缓冲区,大小是8192Byte,也就是8KB ,能够减少访问磁盘的次数,提高文件读取性能;它们都用到了装饰器模式;将FilteOutputStream装到里面,所以 BufferedOutputStream 是 依赖FilteOutputStream 的;

当传输的文件特别大的时候,BufferInputStream的优点就体现出来了 ,带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小(默认8KB)的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!这就是两者的区别

BufferedOutputStream什么时候会往磁盘中写数据呢?

  • 第①种:缓存区满了,写出去!
  • 第②种:flush()方法被调用,写出去!
  • 第③种:close()方法被调用,写出去! 

因为,close()方法被调用的时候,会先调用flush()方法。

如何设置缓冲区大小

看到了吗?构造方法的第二个参数就是缓冲区大小,可以自己自行配置,默认的size就是8192,也就是8kb。

// out 写
BufferedOutputStream in = new BufferedOutputStream(new FileOutputStream("D:\\out.txt"),8192);
// in  读
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\in.txt"),8192);

区别

通过介绍,对它们内部的也就有了一定的了解了;

在这里插入图片描述

BufferedOutputStream 真的比 FileOutputStream 快吗?

为了验证这个这个问题,我们需要做两轮测试,通过写入少量的数据和大量数据对比一下它们之间的速度如何;

第一轮测试 :每次只写一个字节

这一轮测试里面,会延时5秒,在这5秒内不停地往文件中写入一个字节的数据;我们看看5秒后BufferedOutputStream 和 FileOutputStream 能写多少数据,代码如下,(注意:这2个测试方法用到了一个共享变量run,所以测试时一定要分开运行,千万不可以一起运行这个2个测试方法,否则测试数据不准确)

    volatile boolean run = true; // 标志位
   // 不带缓冲区 每次只写一个字节
    @Test
    public void fileWriteOneByte() throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\FileOutputStream_one.txt");
        // 延时5秒
        fiveSeconds();
        while (run){
            // 每次写一个字节
            fileOutputStream.write(1);
        }
        fileOutputStream.flush();
        fileOutputStream.close();
    }
    // 带缓冲区-->每次只写一个字节
    @Test
    public void bufferWriteOneByte() throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\BufferedOutputStream_one.txt");
        BufferedOutputStream bufferedInputStream = new BufferedOutputStream(fileOutputStream);
        // 延时5秒
        fiveSeconds();
        while (run){
            // 每次写一个字节
            bufferedInputStream.write((byte)1);
        }
        bufferedInputStream.flush();
        bufferedInputStream.close();
    }
    /**
     * 延时5秒
     */
    private void fiveSeconds(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 睡5秒
                    Thread.sleep(5000);
                    // 跳出死循环
                    run = false;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

运行后,我们看看结果,显而易见,带缓冲区的BufferedOutputStream在5秒内写入了300M的数据,而不带缓冲区的FileOutputStream在5秒内只写入了1.71M的数据;这个读写速度对比,简直就是碾压型的;

在这里插入图片描述

所以我宣布,第一轮 带缓冲区的BufferedOutputStream 获胜!!!

第二轮测试:每次写入81920个字节(80KB)

这一次我们加大量级,当它们每次都写入81920个字节时,也就是80K,看看这2种方式在5秒内能写多少数据,写的速度会有什么变化呢?谁写的更多呢?让我们拭目以待,上代码 (注意:这2个测试方法用到了一个共享变量run,所以测试时一定要分开运行,千万不可以一起运行这个2个测试方法,否则测试数据不准确)

   volatile boolean run = true;
    // 每次写81920个字节
    @Test
    public void file() throws IOException {
        byte[] bytes = new byte[81920];
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\FileOutputStream_81920.txt");
        // 延时5秒
        fiveSeconds();
        while (run){
            // 每次写入 81920 个字节
            fileOutputStream.write(bytes);
        }
        fileOutputStream.flush();
        fileOutputStream.close();
    }
    // 每次写81920个字节
    @Test
    public void bufferFile() throws IOException {
        byte[] bytes = new byte[81920];
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\BufferedOutputStream_81920.txt");
        BufferedOutputStream bufferedInputStream = new BufferedOutputStream(fileOutputStream,81920);
        // 延时5秒
        fiveSeconds();
        while (run){
            // 每次写入 81920 个字节
            bufferedInputStream.write(bytes);
        }
        bufferedInputStream.flush();
        bufferedInputStream.close();
    }
    // 延时5秒
    private void fiveSeconds(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 睡5秒
                    Thread.sleep(5000);
                    // 跳出死循环
                    run = false;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

通过结构可以看到,带缓冲区的BufferedOutputStream在5秒内写入了将近4.5G的数据,而不带缓冲区的FileOutputStream 在5秒内写入了 6.87G的数据, FileOutputStream 反而更快了;

在这里插入图片描述

所以我宣布,第二轮 不带缓冲区的FileOutputStream 获胜!!!

结论

通过以上的数据可以得出结论,谁快谁慢是根据实际情况来决定的,而不是说带了缓冲区就一定快;

  • 每次写入的数据量小的情况下,带缓冲区的BufferedOutputStream效率更快;
  • 每次写入的数据量比较大时,不带缓冲区的 FileOutputStream 效率更快;

所以,大家在选择的时候就需要根据实际情况来决定使用哪种IO流了,而大部分情况下,FileOutputStream 就已经足够了,只需要将写入的数据量大一点即可;

到此这篇关于Java中IO流的BufferedOutputStream和FileOutputStream对比的文章就介绍到这了,更多相关Java的IO流BufferedOutputStream内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中反射的应用

    Java中反射的应用

    这篇文章主要介绍了Java中反射的应用,通过反射,我们可以在运行时检查类的属性、方法和构造函数,并且可以在不知道类名的情况下创建对象、调用方法和访问属性,需要的朋友可以参考下
    2023-10-10
  • IDEA中Java出现无效的源发行版错误的解决办法

    IDEA中Java出现无效的源发行版错误的解决办法

    这篇文章主要给大家介绍了关于IDEA中Java出现无效的源发行版错误的解决办法,IDEA中Java出现⽆效的源发⾏版解决办法出现该问题的原因是项⽬Project当中的jdk与电脑当中的jdk版本不⼀致造成的,需要的朋友可以参考下
    2023-10-10
  • SpringBoot在自定义类中调用service层等Spring其他层操作

    SpringBoot在自定义类中调用service层等Spring其他层操作

    这篇文章主要介绍了SpringBoot在自定义类中调用service层等Spring其他层操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Spring Cloud实现灰度发布的示例代码

    Spring Cloud实现灰度发布的示例代码

    这篇文章主要为大家详细介绍了Spring Cloud实现灰度发布的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-09-09
  • Java数据类型之引用数据类型解读

    Java数据类型之引用数据类型解读

    这篇文章主要介绍了Java数据类型之引用数据类型,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 浅析 ArrayList 和 LinkedList 有什么区别

    浅析 ArrayList 和 LinkedList 有什么区别

    ArrayList 和 LinkedList 有什么区别,是面试官非常喜欢问的一个问题。今天通过本文给大家详细介绍下,感兴趣的朋友跟随小编一起看看吧
    2020-10-10
  • Java实现人脸识别登录、注册等功能(最新完整版)

    Java实现人脸识别登录、注册等功能(最新完整版)

    这段时间由于学校实行静态化管理,寝室门和校门都是用了人脸识别的装置,本系列项目从设计到实现源码全部开源免费学习使用,对Java实现人脸识别登录、注册功能感兴趣的朋友一起看看吧
    2022-05-05
  • java 中冒泡、二分、快速算法详解

    java 中冒泡、二分、快速算法详解

    这篇文章主要介绍了java 中冒泡、二分、快速算法详解的相关资料,需要的朋友可以参考下
    2017-06-06
  • Java 模拟银行自助终端系统

    Java 模拟银行自助终端系统

    本系统模拟银行用户使用ATM机开户、查询、存款、取款功能,要求使用java语言编程实现。这篇文章主要介绍了Java 模拟银行自助终端系统的相关资料,需要的朋友可以参考下
    2016-10-10
  • mybatis中嵌套使用foreach需要注意的坑

    mybatis中嵌套使用foreach需要注意的坑

    在使用MyBatis进行数据库操作时,如果需要在一个大的foreach标签中嵌套另一个foreach,需要注意内层foreach的item属性不能与外层重复,如果出现重复,会导致绑定参数时找不到正确的参数,从而抛出异常
    2024-09-09

最新评论