Java IO流介绍以及缓冲为何能提升性能

        流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。

        Java IO 也称为IO流,它的核心就是对系统文件的操作、和系统之间读写。IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,非要用字符流处理也行,但是可能会遇到问题或数据损坏,因为字符流可能会将二进制数据解释为字符,导致意外的结果如果是关系到中文(文本)的,用字符流好点。

        IO流的本质是数据传输,并且流是单向的。

        字节流的基本单位为字节(Byte),一个字节通常为 8 位。字节(Byte,简写为B)一般用作数据存储单位,而数据传输大多以位(bit,简写为b)为单位。 一个位代表一个0 或1(即二进制),每8 个位组成1 个字节。

数据持久化:

        所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列。

        我们使用FileWriter向demo.txt中写入了“demo”这四个字符,我们写入的“demo”被编码为了“64 65 6D 6F”,字符流在输出前实际上是要完成Unicode码元序列到相应编码方式的字节序列的转换,所以它会使用内存缓冲区来存放转换后得到的字节序列,等待都转换完毕再一同写入磁盘文件中。

流关闭

流是有起点和终点的字节序列的集合,通过流可以读写设备中的数据, 这儿的设备可以是文件, 内存, ….  IO操作属于资源操作,一定要记得关闭 

示例方法:

为什么一定要close()呢?

* A:让流对象变成垃圾,这样就可以被垃圾回收器回收了

* B:通知系统去释放跟该文件相关的资源

流分类

根据数据处理的不同类型分为:字节流和字符流

字节流:OutputStream 和 InputStream 为基类。

字符流:Writer 和 Reader 为基类。

根据数据流向不同分为:输入流和输出流

输出流:OutputStream 和 Writer 为基类。

输入流:InputStream 和 Reader 为基类。

Io框架图

        虽然IO 有很多,但是最基础的四个类是InputStreamOutputStreamReaderWriter。其他的诸如文件流都是在这四个类的基础上扩展的。比如,我们经常使用的文件读写流,实际上是调用了底层系统的read()write()方法。其他;流都是上面这四类流子类,方法也是通过这两个方法衍生的。而且大部分的IO源码都是native的,也就是说它们是用C/C++写的,这是我们在其他高级语言中无法实现的。

InputStream -- 字节输入流

OutputStream -- 字节输出流

Reader -- 字符输入流

Writer -- 字符输出流

        所有以Stream结尾的流类都是字节流类, 在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。以Reader结尾的流类是字符输入流类, 以Writer结尾的流类是字符输出流类。输入/输出流, 是以当前程序为参照, 把数据从其他资源里面传送到内存里面,就是输入流,反之。把数据从内存传送到其他资源就是输出流。

 不同流的作用

流的性能提升

        使用缓冲区能大幅度提升流性能,什么是缓冲

缓冲:     

缓冲的作用

如果不设置缓冲的话,CPU相对于一个文件的每个字节都需要取一个存一个。设置缓冲区的话:

CPU通常会使用 DMA (将字节积攒一定量在请求cpu发送数据就是DMA方式,cpu成为被调用者,这之后cpu在执行操作将内存数据持久化到硬盘)方式去执行 I\O流 操作。CPU 将这个工作交给DMA控制器来做,自己腾出时间做其他的事,当DMA完成工作时,DMA会主动告诉CPU“操作完成”。这时,CPU接管后续工作。在此,CPU 是被动的。DMA是专门 做 I\O 与 内存 数据交换的,不仅自身效率高,也节约了CPU时间。

 缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,类似数据库的批量操作,显然效率比较高。还节省CPU的使用。

总结:使用缓冲处理流包装就是一堆一堆的干活,还能不用CPU多次处理数据转换,只是设置一下数据转换成功后的文件。不使用缓冲处理流包装就是CPU傻傻的一个字节一个字节循环来干活存储写入文件中,相比可见效率明显变慢  。

再简单说缓冲区的优势以文件流的写入为例,如果我们不使用缓冲区,那么每次写操作 CPU 都会和低速存储设备也就是磁盘进行交互,那么整个写入文件的速度就会受制于低速的存储设备(磁盘)。但如果使用缓冲区的话,每次写操作会先将数据保存在高速缓冲区内存上,当缓冲区的数据到达某个阈值之后,再将文件一次性写入到磁盘上。因为内存的写入速度远远大于磁盘的写入速度,所以当有了缓冲区之后,文件的写入速度就被大大提升了。

                  

 BufferedInputStream/BufferedOutputStream

BufferedReader/BufferedWriter

BufferedWriter 和 BufferedReader 为带有默认缓冲的字符输出输入流,因为有缓冲区所以很效率比没有缓冲区的很高。

默认有8192个字符的缓冲区。

br.readLine()  一次可以读一行

bw.newLine();  换行

bw.flush();使用缓冲区中的方法,将数据刷新到目的地文件中去。

bw.close();关闭缓冲区,同时关闭了fw流对象

性能测试示例
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
 
public class WriteExample {
    public static void main(String[] args) throws IOException {
        // 构建写入内容
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 1000000; i++) {
            stringBuilder.append("ABCDEFGHIGKLMNOPQRSEUVWXYZ");
        }
        // 写入内容
        final String content = stringBuilder.toString();
        // 存放文件的目录
        final String filepath1 = "/Users/mac/Downloads/io_test/write1.txt";
        final String filepath2 = "/Users/mac/Downloads/io_test/write2.txt";
        final String filepath3 = "/Users/mac/Downloads/io_test/write3.txt";
        final String filepath4 = "/Users/mac/Downloads/io_test/write4.txt";
        final String filepath5 = "/Users/mac/Downloads/io_test/write5.txt";
        final String filepath6 = "/Users/mac/Downloads/io_test/write6.txt";
 
        // 方法一:使用 FileWriter 写文件
        long stime1 = System.currentTimeMillis();
        fileWriterTest(filepath1, content);
        long etime1 = System.currentTimeMillis();
        System.out.println("FileWriter 写入用时:" + (etime1 - stime1));
 
        // 方法二:使用 BufferedWriter 写文件
        long stime2 = System.currentTimeMillis();
        bufferedWriterTest(filepath2, content);
        long etime2 = System.currentTimeMillis();
        System.out.println("BufferedWriter 写入用时:" + (etime2 - stime2));
 
        // 方法三:使用 PrintWriter 写文件
        long stime3 = System.currentTimeMillis();
        printWriterTest(filepath3, content);
        long etime3 = System.currentTimeMillis();
        System.out.println("PrintWriterTest 写入用时:" + (etime3 - stime3));
 
        // 方法四:使用 FileOutputStream  写文件
        long stime4 = System.currentTimeMillis();
        fileOutputStreamTest(filepath4, content);
        long etime4 = System.currentTimeMillis();
        System.out.println("FileOutputStream 写入用时:" + (etime4 - stime4));
 
        // 方法五:使用 BufferedOutputStream 写文件
        long stime5 = System.currentTimeMillis();
        bufferedOutputStreamTest(filepath5, content);
        long etime5 = System.currentTimeMillis();
        System.out.println("BufferedOutputStream 写入用时:" + (etime5 - stime5));
 
        // 方法六:使用 Files 写文件
        long stime6 = System.currentTimeMillis();
        filesTest(filepath6, content);
        long etime6 = System.currentTimeMillis();
        System.out.println("Files 写入用时:" + (etime6 - stime6));
 
    }
 
    /**
     * 方法六:使用 Files 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void filesTest(String filepath, String content) throws IOException {
        Files.write(Paths.get(filepath), content.getBytes());
    }
 
    /**
     * 方法五:使用 BufferedOutputStream 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void bufferedOutputStreamTest(String filepath, String content) throws IOException {
        try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                new FileOutputStream(filepath))) {
            bufferedOutputStream.write(content.getBytes());
        }
    }
 
    /**
     * 方法四:使用 FileOutputStream  写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void fileOutputStreamTest(String filepath, String content) throws IOException {
        try (FileOutputStream fileOutputStream = new FileOutputStream(filepath)) {
            byte[] bytes = content.getBytes();
            fileOutputStream.write(bytes);
        }
    }
 
    /**
     * 方法三:使用 PrintWriter 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void printWriterTest(String filepath, String content) throws IOException {
        try (PrintWriter printWriter = new PrintWriter(new FileWriter(filepath))) {
            printWriter.print(content);
        }
    }
 
    /**
     * 方法二:使用 BufferedWriter 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void bufferedWriterTest(String filepath, String content) throws IOException {
        try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filepath))) {
            bufferedWriter.write(content);
        }
    }
 
    /**
     * 方法一:使用 FileWriter 写文件
     * @param filepath 文件目录
     * @param content  待写入内容
     * @throws IOException
     */
    private static void fileWriterTest(String filepath, String content) throws IOException {
        try (FileWriter fileWriter = new FileWriter(filepath)) {
            fileWriter.append(content);
        }
    }
}

在查看结果之前,我们先去对应的文件夹看看写入的文件是否正常,如下图所示

从上述结果可以看出,每种方法都正常写入了 26 MB 的数据,它们最终执行的结果如下图所示:

通过结果可以看出有缓冲区的是性能最强的 

------------------------------------------与正文内容无关------------------------------------
如果觉的文章写对各位读者老爷们有帮助的话,麻烦点赞加关注呗!小弟在这拜谢了!
如果您觉得我的文章在某些地方写的不尽人意或者写的不对,从而让你对你人生观产生颠覆(概不负责),需要斧正,麻烦在评论区不吝赐教,作者看到后会根据您的提示查阅文章进行修改,还这世间一个公理一片蓝天

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/290990.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中文大语言模型 Llama-2 7B(或13B) 本地化部署 (国内云服务器、GPU单卡16GB、中文模型、WEB页面TextUI、简单入门)

本文目的是让大家先熟悉模型的部署&#xff0c;简单入门&#xff1b;所以只需要很小的算力&#xff0c;单台服务器 单GPU显卡&#xff08;显存不低于12GB&#xff09;&#xff0c;操作系统需要安装 Ubuntu 18.04。 1 服务器&操作系统 1.1服务器的准备 准备一台服务器 单张…

【论文阅读笔记】两篇完整模态脑瘤分割

两篇完整模态脑瘤分割论文&#xff0c;都是使用Transformer&#xff0c;没有什么特别的特色&#xff0c;也没有开源代码&#xff0c;因此只是简单记录一下。 3D CATBraTS: Channel attention transformer for brain tumour semantic segmentation El Badaoui R, Coll E B, Ps…

Linux第2步_创建虚拟机

VMware软件安装好后&#xff0c;就可以创建虚拟机了。 一、虚拟机对CPU的要求较高 i7 处理器&#xff1a;CPU&#xff1a;Intel(R) Core(TM) i7-8700 CPU 3.20GHz 3.19 GHz 内核数&#xff1a;6 线程数&#xff1a; 12 最大睿频频率&#xff1a; 4.60 GHz 英特尔 睿…

springcloud之集成nacos config

写在前面 源码 。 本文看下如下集成nacos config组件。 1&#xff1a;常见配置方式分析 我们先来看下常见的配置方式都有哪些&#xff0c;以及其有什么优点和缺点。 硬编码 优点&#xff1a;hardcode&#xff0c;除了开发的时候快些&#xff0c;爽一下&#xff0c;有个屁优…

网络机顶盒哪个好?耗时30天盘点网络机顶盒排名

网络机顶盒作为电视机的最佳搭档&#xff0c;是看片必备&#xff0c;网络机顶盒的品牌非常多让新手们在选购时往往不知道网络机顶盒哪个好&#xff0c;我耗时一个月测评了十几款热门的电视机顶盒&#xff0c;通过各个角度深度对比后整理了网络机顶盒排名&#xff0c;在选购时大…

NFC物联网开发在智慧校园中的应用

近年来&#xff0c;校园信息化建设速度加快&#xff0c;以物联网为基础、以各种应用服务系统为载体的智慧校园将教学、管理和校园生活充分融合&#xff0c;形成了工作、学习和生活的一体化环境。沉寂已久的NEC 技术&#xff0c;得益于智能手机的普及、无线网络数据速率提高&…

如何构建高效测试体系?掌握5大自动化测试模式就够了

软件开发过程中&#xff0c;高效的自动化测试体系是提升测试效率、保证产品质量关键&#xff0c;一个全面的测试体系涵盖多个维度&#xff0c;从功能性到用户界面&#xff0c;再到性能和安全性。 每个维度均采用不同的测试模式来满足特定的需求和解决特别的挑战&#xff0c;本…

Linux_源码编译安装LAMP

1. 安装httpd服务 在配置 Apache 网站服务之前&#xff0c;需要正确安装好 httpd 服务器软件。httpd 服务器的安装可以选用 RPM 安装、源码编译安装这两种方式&#xff0c;前者相对比较简单、快速&#xff0c;但是在功能上存在一定的局限性。在实际的生产环境中&#xff0c;使…

openGauss学习笔记-174 openGauss 数据库运维-备份与恢复-导入数据-管理并发写入操作

文章目录 openGauss学习笔记-174 openGauss 数据库运维-备份与恢复-导入数据-管理并发写入操作174.1 事务隔离说明174.2 写入和读写操作174.3 并发写入事务的潜在死锁情况 openGauss学习笔记-174 openGauss 数据库运维-备份与恢复-导入数据-管理并发写入操作 174.1 事务隔离说…

K线+直线 现货黄金也可能变现

现货黄金行情怎么做&#xff0c;这是投资者需要思考的问题。幸运的是&#xff0c;现在市面上有很多书籍&#xff0c;是其他有经验、有想法的投资者们对其经验的总结和分享&#xff0c;此外网络上还有不同的文章和各种各样的视频介绍相关交易经验&#xff0c;这都是可以让我们借…

VUE3跳转页面时 定时器未清除解决

一,问题 1、在vue中使用setTimeout定时器的时候&#xff0c;可能会遇到关不掉的情况&#xff0c;会存在明明已经在beforeDestroy和destroyed中设置了定时器清除了&#xff0c;但是有时候没生效&#xff0c;定时器还会继续执行。 2、在这里需要说一下setTimeout的使用场景&…

Kubernetes 配置Pod使用代理上网

配置Kubernetes Pod使用代理上网 在企业网络环境中进行Kubernetes集群的管理时&#xff0c;经常会遇到需要配置Pods通过HTTP代理服务器访问Internet的情况。这可能是由于各种原因&#xff0c;如安全策略限制、网络架构要求或者访问特定资源的需要。本文将介绍配置Kubernetes中…

天融信TOPSEC Cookie 远程命令执行漏洞复现

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、漏洞概述 天融信TOPSEC解决方案包括综合管理系统&#xff0c;各类安…

科研上新 | 第4期:语言-音乐对比预训练;查找表实现的神经网络推理;大模型时代重新定义搜索框架

编者按&#xff1a;欢迎阅读“科研上新”栏目&#xff01;“科研上新”汇聚了微软亚洲研究院最新的创新成果与科研动态。在这里&#xff0c;你可以快速浏览研究院的亮点资讯&#xff0c;保持对前沿领域的敏锐嗅觉&#xff0c;同时也能找到先进实用的开源工具。 本期内容速览 …

草图大师 sketchup pro2023

SketchUp Pro是一款功能强大的三维建模软件&#xff0c;适用于建筑、机械、室内设计等领域。它提供了丰富的绘图工具和灵活的建模选项&#xff0c;支持实时预览和多种设备适配&#xff0c;让用户能够快速高效地创建出逼真的三维模型。SketchUp Pro还具备强大的插件生态和团队协…

【mars3d】FixedRoute的circle没有跟polyline贴着模型的解决方案

问题&#xff1a;【mars3d】官网的贴模型示例中&#xff0c;参考api文档增加了circle的配置&#xff0c;但是FixedRoute的circle没有跟polyline贴着模型 circle: { radius: 10, materialType: mars3d.MaterialType.CircleWave, materialOptions: { color: "#ffff00"…

数仓分层结构

--图片来源尚硅谷 ODS层&#xff1a; 数据存储格式&#xff1a;JSON/TSV gzip压缩&#xff08;默认&#xff09; Operate Data Store -- 存储从mysql业务数据库和日志服务器的日志文件中采集到的数据 -- 日志数据 -- 格式:JSON --业务数据 --历史数据 …

借还款记账表,借款还款记账软件

我们每个人都在为生活奔波&#xff0c;为事业打拼。但有时候&#xff0c;生活中的一些小事情&#xff0c;比如朋友间的借贷、还款&#xff0c;就可能让我们的生活变得有些混乱。为了解决这个问题&#xff0c;一个全新的借还款记账软件【晨曦记账本】横空出世&#xff0c;它不仅…

STM32真的是很落后吗?

今日话题&#xff0c;STM32真的是很落后吗&#xff1f;STM32是否落后于其他技术在很大程度上依赖于具体的应用和需求。虽然我对Python的了解有限&#xff0c;但我认识到STM32在嵌入式领域具有广泛的应用和卓越的性能。值得注意的是&#xff0c;STM32不仅性能卓越&#xff0c;而…

公众号文章如何提高阅读量?媒介盒子教你几招

公众号作为微信运营的主要载体&#xff0c;做得好就能让品牌得到大量曝光&#xff0c;公众号文章作为长文案想要写好还需要一定的技术&#xff0c;今天媒介盒子就来和大家聊聊公众号文章怎么写才能提高阅读量&#xff1a; 一、 内容干货满足读者求知欲 只要你的文章实用性强&…