提升Java IO性能!探究BufferedOutputStream的奥秘

举报
bug菌 发表于 2023/10/18 12:41:14 2023/10/18
【摘要】 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!

  咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~

在这里插入图片描述

🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

  在Java开发过程中,IO操作是我们必定会遇到的问题。而对于IO操作的性能问题,也是我们需要特别关注的问题。在Java中,我们可以通过使用BufferedOutputStream来提升IO操作的性能。本文将深入探讨BufferedOutputStream的奥秘,以提升Java IO性能。

摘要

本文将从以下几个方面入手,探究BufferedOutputStream的奥秘:

  1. BufferedOutputStream的概述和使用方法
  2. BufferedOutputStream的源代码解读
  3. BufferedOutputStream的性能测试和分析

  通过对BufferedOutputStream的深入研究,我们将了解到如何正确使用BufferedOutputStream来提升IO操作的性能,同时也可以更深入地了解Java IO的实现原理。

BufferedOutputStream类

概述

  BufferedOutputStream是Java中的一个IO流,它是OutputStream类的子类。与OutputStream不同的是,BufferedOutputStream提供了一种缓冲机制,能够将数据写入内存缓存区中,当缓存区达到一定大小时,才一次性写入到磁盘中。这种缓冲机制能够提高IO操作的效率。

常用方法

BufferedOutputStream有以下几个重要的方法:

  1. 构造方法:BufferedOutputStream(OutputStream out)
  2. 写入方法:void write(int b)
  3. 写入方法:void write(byte[] b, int off, int len)
  4. 刷新方法:void flush()
  5. 关闭方法:void close()

使用BufferedOutputStream的步骤如下:

  1. 创建输出流对象:BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"));
  2. 写入数据:bos.write("hello world".getBytes());
  3. 刷新数据:bos.flush();
  4. 关闭流:bos.close();

  需要注意的是,当使用BufferedOutputStream的时候,不要忘记使用flush()方法将缓存区中的数据写入磁盘中,否则数据可能不会被写入磁盘中。

源码分析

下面是BufferedOutputStream的源代码:

public class BufferedOutputStream extends FilterOutputStream {
    protected byte[] buf;
    protected int count;

    public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }

    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

    public synchronized void write(int b) throws IOException {
        if (count >= buf.length) {
            flushBuffer();
        }
        buf[count++] = (byte) b;
    }

    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) {
            flushBuffer();
        }
        System.arraycopy(b, off, buf, count, len);
        count += len;
    }

    public synchronized void flush() throws IOException {
        flushBuffer();
        out.flush();
    }

    public void close() throws IOException {
        flush();
        out.close();
    }

    protected void flushBuffer() throws IOException {
        if (count > 0) {
            out.write(buf, 0, count);
            count = 0;
        }
    }
}

  从源代码中可以看出,BufferedOutputStream的实现原理就是在内部维护一个缓存区buf。当数据写入缓冲区后,如果缓冲区已满,就会调用flushBuffer()方法将缓冲区中的数据写入到磁盘中。同时,在关闭流之前,也必须调用flush()方法将缓存区中的数据写入磁盘中。

优缺点

  BufferedOutputStream 是 Java I/O 中的一个包装类,它可以提高 I/O 的性能。BufferedOutputStream 的主要作用是增加输出流的缓存。缓冲区的存在可以减少写磁盘的次数,因为数据都是先写入到内存中的缓存区中,等缓存区满了,再一次性将缓存区中的数据写入磁盘。这个过程可以提高写入磁盘的效率。

优点:

1.提高了写入磁盘的效率,缓冲数据减少了写磁盘的次数,减少了磁盘的读写次数,提高了程序的性能。

2.提供了对 I/O 操作的控制,可指定缓存区大小以及写入数据的位置。

3.可以按照字节写入数据,适用于所有类型的数据流。

4.与其他 I/O 类共同存在时,BufferedOutputStream 可以提供缓存增强功能。

缺点:

1.如果缓冲区较小,会增加读写 I/O 的次数,从而降低程序的性能。

2.如果程序写入的数据不满缓冲区大小,程序必须手动清空缓存区,否则写入的数据不会输出到文件。

应用场景

  BufferedOutputStream 适用于需要对数据流进行控制的场景,可以缓存数据减少磁盘的读写次数,提高程序的性能。在网络编程中,可以使用 BufferedOutputStream 提高传输效率,也可用于处理较大的音频、视频文件等数据流。此外,当需要在其他 I/O 类别中使用时,BufferedOutputStream 也可以提供缓存增强功能。

性能测试和分析

测试代码

为了测试BufferedOutputStream的性能,我们编写了如下测试代码:

package com.example.javase.io.bufferedOutputStream;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

/**
 * @Author bug菌
 * @Date 2023-10-15 20:29
 */
public class BufferedOutputStreamTest {

    public static void main(String[] args) throws Exception {
        String text = "hello world,jym!!!";
        int count = 1000000;

        long start1 = System.currentTimeMillis();
        FileOutputStream fos = new FileOutputStream("./template/hello.txt");
        for (int i = 0; i < count; i++) {
            fos.write(text.getBytes());
        }
        fos.close();
        long end1 = System.currentTimeMillis();

        long start2 = System.currentTimeMillis();
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("./template/hello.txt"));
        for (int i = 0; i < count; i++) {
            bos.write(text.getBytes());
        }
        bos.close();
        long end2 = System.currentTimeMillis();

        System.out.println("普通输出流耗时:" + (end1 - start1) + "ms");
        System.out.println("带缓存输出流耗时:" + (end2 - start2) + "ms");
    }
}

测试代码分析

根据如上测试代码进行分析:

  1. 导入需要的包。
  2. 创建一个字符串变量 text,并赋值为 hello world,jym!!!,创建一个整型变量 count,并赋值为 1000000。
  3. 通过 System.currentTimeMillis() 获取当前时间戳,作为开始时间 start1。
  4. 创建 FileOutputStream 对象 fos,指向文件路径为 ./template/hello.txt
  5. 使用 for 循环写入 count 次数据,每次调用 fos.write() 方法写入 text 转换为字节数组后的数据。
  6. 关闭 fos 流。
  7. 通过 System.currentTimeMillis() 获取当前时间戳,作为结束时间 end1。
  8. 通过 System.currentTimeMillis() 获取当前时间戳,作为开始时间 start2。
  9. 创建 BufferedOutputStream 对象 bos,通过构造方法传入 FileOutputStream 对象和缓存大小(默认为 8192 字节)。
  10. 使用 for 循环写入 count 次数据,每次调用 bos.write() 方法写入 text 转换为字节数组后的数据。
  11. 关闭 bos 流。
  12. 通过 System.currentTimeMillis() 获取当前时间戳,作为结束时间 end2。
  13. 输出普通输出流和带缓存输出流的耗时差。
  14. 代码执行完毕。

测试结果

测试用例结果如下:

在这里插入图片描述

  测试结果显示,使用BufferedOutputStream后,IO操作的耗时大大减少,性能得到了很大程度的提升。

小结

  本文对Java中的IO操作进行了深入研究,重点关注了BufferedOutputStream的实现原理和使用方法。通过测试,我们也进一步验证了BufferedOutputStream在提高IO操作性能方面的作用。在实际开发中,我们应当更多地使用BufferedOutputStream来提高IO操作的效率,特别是对于大量的数据写入操作。

总结

  通过本文的介绍,我们了解到了BufferedOutputStream的概念、特点、使用方法和实现原理。同时,我们也了解到了如何正确使用BufferedOutputStream来提高IO操作的性能。在实际开发中,我们应当充分利用Java提供的缓存机制,来提高程序的性能。

附录源码

  如上涉及所有源码均已上传同步在「Gitee」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

☀️建议/推荐你

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

📣关于我

我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。