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 的数据,它们最终执行的结果如下图所示:

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

海外 proxy代理Croxyproxy使用教程

什麼是Croxy代理&#xff1f; CroxyProxy是一項線上代理服務。它允許用戶訪問被阻止的網站和應用程式&#xff0c;提供一種安全的方式來訪問互聯網資源&#xff0c;同時維護用戶隱私。與許多其他網路代理不同&#xff0c;它支持幾乎所有類型的網站&#xff0c;包括視頻、搜索引…

北京1月1日起,禁止上路!“老头乐”,乐不起来了?

北京“老头乐”退场 2021年7月&#xff0c;北京市公安局、北京市交通委员会等五部门联合发布《关于加强违规电动三四轮车管理的通告》&#xff0c;明确提出&#xff0c;对通告发布前购买的违规电动三、四轮车设置过渡期&#xff0c;过渡期截至2023年12月31日。过渡期结束后&am…

芯课堂 | LVGL基础知识(二)

引言 在 LVGL 中&#xff0c;用户界面的基本构建块是对象&#xff0c;也称为小部件(widget)。默认情况下&#xff0c;LVGL在背景上绘制旧对象&#xff0c;在前景上绘制新对象。 对象层级(Layers) 创建对象层级顺序 默认情况下&#xff0c;LVGL在背景上绘制旧对象&#xff0c…

优化独立站网页布局,提升30%用户留存

近几年很多老板都意识到私域流量的重要性&#xff0c;也都开始从各类平台转战独立站。但是独立站起步也是困难重重&#xff0c;首先很直接的问题就是独立站的搭建&#xff0c;今天咱们就抛开技术&#xff0c;单纯聊聊网页的排版布局。 1. 忌文字多 不是说不让用文字&#xff…

2023:毕业后工作多年机械转编程——心路历程

还记得当初自己为什么选择计算机&#xff1f; 刚接触计算机的时候&#xff0c;是因为工作接触到了一款国家基本服务的软件&#xff0c;跟几个程序员大神们相处了半年&#xff0c;加班到凌晨也不觉得累。我当时是做的工作对标现在的产品经理&#xff0c;但我当时在公司的岗位仅…

vue前端表单常用的邮箱、电话、身份证、url、Ip等正则式多语言版校验

utils工具类中创建verify.js 常用表單校驗 //正则校验的正则表达式&#xff0c;这里注意正则表达式中的‘\’要使用‘\\’转义 const patterns {"name": "^[a-zA-Z_][0-9a-zA-Z_]{0,}$","phone": "^(13[0-9]|14[5|7]|15[0|1|2|3|4|5|6|7…

数字人对话系统 Linly-Talker(已加入Qwen和GeminiPro加强对话+上传任意图片的数字人)

&#x1f525;&#x1f525;&#x1f525;数字人对话系统 Linly-Talker&#x1f525;&#x1f525;&#x1f525;&#xff08;已加入Qwen和GeminiPro加强对话上传任意图片的数字人&#xff09; English 简体中文 欢迎大家star我的仓库 https://github.com/Kedreamix/Linly-Ta…

Git专栏篇

一、基础知识 二、常用手段 1. 复制其他提交到本分支 目的&#xff1a;现有git仓库&#xff0c;该仓库有两个分支a和b&#xff0c;将a分支的最近三个版本提交内容复制 到b分支的提交上。 在 Linux 系统中&#xff0c;你可以按照以下步骤将分支 A 的最近三个版本的提交内容复…

linux 环境下安装ffmpeg。

参考 https://www.anquanclub.cn/9782.html 下载解压 wget http://www.ffmpeg.org/releases/ffmpeg-3.1.tar.gz tar -zxvf ffmpeg-3.1.tar.gz cd ffmpeg-3.1. ./configure --prefix/usr/local/ffmpeg make && make install 之后在 ffmepg目录下执行 ./ffmpeg -versio…

CMake中引入第三方库

CMake中&#xff0c;如果我们需要引入第三方库&#xff0c;首先想到的是用find_package函数。的确&#xff0c;如果我们引入的第三方库是一些比较标准的库如OpenCV可以用下面的代码。 set(OpenCV_DIR xxxx) # xxxx目录包含OpenCVConfig.cmake find_package(opencv required) #…

XOR运算文件加密示例

前言&#xff1a; XOR加密是一种非常简单的加密技术属于对称加密&#xff08;相同的密钥进行加密和解密&#xff09;&#xff0c;不提供机密性或完整性验证因此不适用于高度敏感的数据&#xff0c;容易受到各种攻击&#xff0c;包括已知明文攻击。在实际应用中&#xff0c;应该…

实时记录和查看Apache 日志

Apache 是一个开源的、广泛使用的、跨平台的 Web 服务器&#xff0c;保护 Apache Web 服务器平台在很大程度上取决于监控其上发生的活动和事件&#xff0c;监视 Apache Web 服务器的最佳方法之一是收集和分析其访问日志文件。 Apache 访问日志提供了有关用户如何与您的网站交互…

外贸客户邮箱采集软件的工作原理

外贸客户邮箱采集软件是专为外贸从业人员设计的工具&#xff0c;旨在帮助用户快速、准确地获取潜在客户的邮箱地址。此类软件在国际贸易中发挥着越来越重要的作用&#xff0c;尤其在当前数字化时代&#xff0c;有效的客户邮箱采集已成为外贸业务成功的关键因素之一。 该软件的…

Volcano Controller控制器源码解析

Volcano Controller控制器源码解析 本文从源码的角度分析Volcano Controller相关功能的实现。 本篇Volcano版本为v1.8.0。 Volcano项目地址: https://github.com/volcano-sh/volcano controller命令main入口: cmd/controller-manager/main.go controller相关代码目录: pkg/co…

一加 Buds 3正式发布:普及旗舰音质 一加用户首选

1月4日&#xff0c;一加新品发布会正式推出旗下新款耳机一加 Buds 3。延续一加经典美学&#xff0c;秉承音质完美主义追求&#xff0c;一加 Buds 3全面普及一加旗舰耳机体验&#xff0c;其搭载旗舰同款“超清晰同轴双单元”&#xff0c;配备49dB 4000Hz超宽频主动降噪&#xff…

pandas时间加减

在 Pandas 中&#xff0c;可以使用加减法运算符(、-)对时间序列进行加减运算。还可以使用 pd.DateOffset 或 pd.Timedelta 对时间序列进行偏移。 示例&#xff1a; import pandas as pd# 创建时间序列 date_rng pd.date_range(start1/1/2020, end1/10/2020, freqD) df pd.D…

万界星空科技MES系统中的生产管理

MES系统能够帮助企业实现生产计划管理、生产过程控制、产品质量管理、车间库存管理、项目看板管理等&#xff0c;提高企业制造执行能力。 万界星空MES系统特点&#xff1a; 1. 采用强大数据采集引擎、整合数据采集渠道&#xff08;RFID、条码设备、PLC、Sensor、IPC、PC等&…

【中小型企业网络实战案例 七】配置限速

相关学习文章&#xff1a; 【中小型企业网络实战案例 一】规划、需求和基本配置 【中小型企业网络实战案例 二】配置网络互连互通【中小型企业网络实战案例 三】配置DHCP动态分配地址 【中小型企业网络实战案例 四】配置OSPF动态路由协议【中小型企业网络实战案例 五】配置可…

C++系列十三:C++中的引用

C中的引用 1. 引用的声明与初始化2. 引用在函数中的应用3. 引用的注意事项与陷阱 引用在C中是一种特殊的变量&#xff0c;它为其他变量提供了一个别名。这意味着&#xff0c;引用和它所引用的变量实际上是同一个实体。通过引用&#xff0c;可以直接访问和修改变量的值&#xff…

Hubery-个人项目经历记录

研究生期间很有幸的进入到了崔老师的组&#xff0c;从此也就进入到了分析人体生理信号的领域&#xff0c;充满挑战的同时也充满了乐趣。借着CSDN整理一下近几年来参与的项目&#xff0c;这里蕴含着我各种美好的回忆&#xff0c;也作为一个展示自己的平台吧。 开始之前&#xff…