提升Java IO性能!探究BufferedOutputStream的奥秘
咦咦咦,各位小可爱,我是你们的好伙伴——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
的奥秘:
BufferedOutputStream
的概述和使用方法BufferedOutputStream
的源代码解读BufferedOutputStream
的性能测试和分析
通过对BufferedOutputStream的深入研究,我们将了解到如何正确使用BufferedOutputStream来提升IO操作的性能,同时也可以更深入地了解Java IO的实现原理。
BufferedOutputStream类
概述
BufferedOutputStream
是Java中的一个IO流,它是OutputStream
类的子类。与OutputStream
不同的是,BufferedOutputStream
提供了一种缓冲机制,能够将数据写入内存缓存区中,当缓存区达到一定大小时,才一次性写入到磁盘中。这种缓冲机制能够提高IO操作的效率。
常用方法
BufferedOutputStream有以下几个重要的方法:
- 构造方法:
BufferedOutputStream(OutputStream out)
- 写入方法:
void write(int b)
- 写入方法:
void write(byte[] b, int off, int len)
- 刷新方法:
void flush()
- 关闭方法:
void close()
使用BufferedOutputStream
的步骤如下:
- 创建输出流对象:
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))
; - 写入数据:
bos.write("hello world".getBytes())
; - 刷新数据:
bos.flush()
; - 关闭流:
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");
}
}
测试代码分析
根据如上测试代码进行分析:
- 导入需要的包。
- 创建一个字符串变量 text,并赋值为
hello world,jym!!!
,创建一个整型变量 count,并赋值为 1000000。 - 通过
System.currentTimeMillis()
获取当前时间戳,作为开始时间 start1。 - 创建
FileOutputStream
对象 fos,指向文件路径为./template/hello.txt
。 - 使用 for 循环写入
count
次数据,每次调用fos.write()
方法写入 text 转换为字节数组后的数据。 - 关闭 fos 流。
- 通过
System.currentTimeMillis()
获取当前时间戳,作为结束时间 end1。 - 通过
System.currentTimeMillis()
获取当前时间戳,作为开始时间 start2。 - 创建
BufferedOutputStream
对象 bos,通过构造方法传入FileOutputStream
对象和缓存大小(默认为 8192 字节)。 - 使用 for 循环写入
count
次数据,每次调用bos.write()
方法写入text
转换为字节数组后的数据。 - 关闭 bos 流。
- 通过
System.currentTimeMillis()
获取当前时间戳,作为结束时间 end2。 - 输出普通输出流和带缓存输出流的耗时差。
- 代码执行完毕。
测试结果
测试用例结果如下:
测试结果显示,使用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电子书籍、简历模板等海量资料。
- 点赞
- 收藏
- 关注作者
评论(0)