IO流(2)-缓冲流

news/2024/5/20 4:11:52

1. 缓冲流的简单介绍

我们上贴说到了 FileInputStream,FileOutputStream,FileReader,FileWriter。 

其实这四个流,我们通常把它叫做原始流,它们是比较偏底层的;而今天我们要说的四个缓冲流,如下图所示,叫包装流,也叫处理流,它们之间也有继承关系自下而上,并且它们都可以提高原始流读写数据的性能。

2. 为什么要用到缓冲流

我先来说一下为什么要用到字节缓冲流,我们来看下面这幅图。

现在有一个需求,将D盘下一个大小为 16KB 的文件拷贝到C盘,该怎么做?

如果我们采用原始的字节流或者字符流,我们首先定义一个大小为 1KB 的数组,然后通过输入流读取数据,将数据读取到字节数组中, 然后再使用输出流将数组中的数据写入到C盘,由于数据源大小为16KB,我们输入流需要读取16次,输出流同样也要输出16次,这样合计就是32次,非常消耗系统资源,那么有没有什么更好的解决方案呢,在不改变题目的前提下,让我们减少与磁盘的IO次数,提高程序整体的运行效率呢?

当然是有的,它就是我们接下来要说的缓冲流

3. 缓冲流是如何提高读写性能的?

如上图所示,缓冲流之所以能提高读写的性能,是因为如果我们使用缓存输入流,那么它就会在内存中开辟一处大小为8KB输入缓存区,缓存输出流也是同样的道理,它也会在内存中开辟一处大小为8KB的输出缓存区;

还拿刚才的例子来说,当我们读取文件时,这8KB的输入缓存区会直接读满数据源中8KB的资源,然后,我们的缓存输出流在输出时,会从这8KB的缓存区读取内容,读取到内容之后,再写入另外8KB的输出缓冲区,当输出缓存区满了之后,会一次性的将8KB的数据以下次写入硬盘,由于内存中的读写效率非常的高,所以时间可以忽略不计,我们只看从D盘到内存和从内存到C盘的次数.

16KB需要读取两次,也需要输出两次,共计四次。而我们使用之前输入流和输出流,需要读写32次,效率提高了8倍,可以说是极大地提高了读写效率。

我们下面来看一下源码就知道了

3.1 BufferedInputStream 源码

 上图是 BufferdInputStream 的源码类,这里定义了一个 int变量 大小为 8192,就是1024 * 8

 往下翻可以找到 BufferdInputStream 的构造方法,我们点击 this 查看

 可以看到这里它 new 了一个数组,size 就是我们刚才说的那个 int 值,如此看来就是new 了一个大小为 8KB 的字节数组。

3.2 BufferdOutputStream 源码

这里也是一样,8192 ,也为8KB,点击this 方法查看如下

它也是 new 了一个大小为 8KB 的字节数组。

3.3 BufferReader 源码

 以上即为 BufferdReader 的源码,可以看到它这里也是 new 了一个大小为 8KB 的字符数组

3.4 BufferWriter 源码

 以上为 BufferdWriter 的源码,也是定义了一个大小为 8BK 的字符数组。

总的来说,缓冲流能提高读写效率的原因,是因为它们会在内存开辟缓存空间,减少了与磁盘的IO次数,从而提高了读写效率。

4. BufferInputStream和BufferOutputStream

BufferdInputStream 和 BufferdOutputStream 的构造器如下所示,它们分别需要传入一个 InputStream 的对象 和 OutputStream 的对象。

刚才我们看源码也看到了,其实BufferedInputStream还有一个构造方法,我们可以自行传入一个数组的大小,如果不传入,默认为8KB,我们也可以重载该构造方法,自行传入,例如传入一个 1024 * 16 ,那么就是在内存中创建一个 16KB大小的 缓存输入流空间,其它流也是同样的道理。

我做一个简单的案例,还是从C盘拷贝一个文件到D盘,如下代码

public static void main(String[] args) {// 创建输入流对象InputStream is = null;// 创建输出流对象OutputStream os = null;// 创建字节缓冲输入流对象BufferedInputStream bis = null;// 创建字节缓冲输出流对象BufferedOutputStream bos = null;try {is = new FileInputStream("user-service/test.txt");os = new FileOutputStream("D:/test2.txt");bis = new BufferedInputStream(is);bos = new BufferedOutputStream(os);// 定义一个大小为 1024 的字节数组byte[] bytes = new byte[1024];// 定义一个长度变量,记录读取到的字节数量int length;// 定义循环读取文件内容while((length = bis.read(bytes)) != -1){// 将读取到的内容写入磁盘bos.write(bytes,0,length);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {if (bos != null)bos.close();if (bis != null)bis.close();if (os != null)os.close();if (is != null)is.close();} catch (IOException e) {e.printStackTrace();}}}

运行上述代码,得到如下结果,我们到D盘查看,可以看到拷贝成功

5. BufferedReader 与 BufferedWriter

BufferedReader 与 BufferedWriter 的构造器根字节缓冲输入流,字节缓冲输出流极其相似,都是要传入一个流对象,这里就不需要我做过多的赘述了,适用语法也半差不差;

在字符缓冲输入流中还新增了一个方法,可以一行一行的读取数据

在字符缓冲输出流中也新增了一个方法,换行操作

我们把刚才字节缓冲流的代码稍微改动一下仍然可以用,如下

public static void main(String[] args) {// 创建输入流对象Reader r = null;// 创建输出流对象Writer w = null;// 创建字节缓冲输入流对象BufferedReader br = null;// 创建字节缓冲输出流对象BufferedWriter bw = null;try {r = new FileReader("user-service/test.txt");w = new FileWriter("D:/test3.txt");br = new BufferedReader(r);bw = new BufferedWriter(w);// 定义一个大小为 1024 的字节数组char[] chars = new char[1024];// 定义一个长度变量,记录读取到的字节数量int length;// 定义循环读取文件内容while((length = br.read(chars)) != -1){// 将读取到的内容写入磁盘bw.write(chars,0,length);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {try {if (bw != null)bw.close();if (br != null)br.close();if (w != null)w.close();if (r != null)r.close();} catch (IOException e) {e.printStackTrace();}}}

运行上述代码,得到如下结果,到D盘查看,发现存在test3.txt 文件 ,点击查看,文件内容也都开碑过来了,说明代码无误。


http://www.mrgr.cn/p/57075808

相关文章

微服务 云原生:搭建 K8S 集群

为节约时间和成本,仅供学习使用,直接在两台虚拟机上模拟 K8S 集群搭建 踩坑之旅 系统环境:CentOS-7-x86_64-Minimal-2009 镜像,为方便起见,直接在 root 账户下操作,现实情况最好不要这样做。 基础准备 关…

vins调试的注意事项

1、摄像头的内参和畸变矫正系数 这个系数不对,没法做,因为下一步没法做对。这个会导致系统无法初始化。 2、对畸变的像素点,求得归一化坐标的方法 理解不同矫正模型的原理,确保矫正对了,得到z1平面的去畸变点。 3、摄…

map,set的封装(基于改造红黑树)

目录 引言 1.迭代器 2.map的[]重载 3.KeyOfValue模板参数 4.整体代码展示 //改造后的红黑树代码 #include <iostream> using namespace std;enum Colour {RED 0,BLACK, };//为了实现map与set封装使用同一个模板红黑树&#xff0c;前者的value是pair&#xff0c;后者…

【玩转Python系列【小白必看】Python多线程爬虫:下载表情包网站的图片

文章目录 前言1. 导入模块和库2. 定义函数 download_image(url, filepath)3. 定义函数 get_page()4. 主程序入口 完整代码运行效果 结束语 前言 本文主要介绍了使用Python编写的多线程爬虫程序&#xff0c;用于下载表情包网站上的图片。通过解析网页内容和使用XPath定位&#x…

python爬虫基础

文章目录 前言爬虫简介urllib库的使用如何获取网页的源码一个类型六个方法一个类型六个方法1、read()方法2、readline()方法3、readlines()方法4、getcode()5、geturl()6、getheaders() urllib下载下载网页下载图片下载视频 请求对象的定制 未完待续 前言 爬虫爬的好牢饭吃的早…

关于K8s的Pod的详解(一)

关于K8s的Pod的详解&#xff08;一&#xff09; Pod和API server的通信加快Pod启动更改Pod的资源Pod 的持久卷的单个访问模式Pod 拓扑分布约束Pod 拓扑分布中的最小域数 Pod 作为k8s创建&#xff0c;调度&#xff0c;管理的基本单位。由上级的Controller对Node上安装的Kubelet发…

云安全攻防(二)之 云原生安全

云原生安全 什么是云原生安全&#xff1f;云原生安全包含两层含义&#xff1a;面向云原生环境的安全和具有云原生特征的安全 面向云原生环境的安全 面向云原生环境的安全的目标是防护云原生环境中的基础设施、编排系统和微服务系统的安全。这类安全机制不一定会具有云原生的…

基于SaaS模式的Java基层卫生健康云HIS系统源码【运维管理+运营管理+综合监管】

云HIS综合管理平台 一、模板管理 模板分为两种&#xff1a;病历模板和报表模板。模板管理是运营管理的核心组成部分&#xff0c;是基层卫生健康云中各医疗机构定制电子病历和报表的地方&#xff0c;各医疗机构可根据自身特点特色定制电子病历和报表&#xff0c;制作的电子病历…

Web-1-网站工作流程介绍

我们学习web开发&#xff0c;首先要知道什么是Web&#xff1f; Web: 全球广域网&#xff0c;也称为万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站 比如我展示的这京东&#xff0c;淘宝唯品会都叫做网站&#xff0c;那么现在大家想一下&#xff0c;你还知道什…

论文笔记:Adjusting for Autocorrelated Errors in Neural Networks for Time Series

2021 NIPS 原来的时间序列预测任务是根据预测论文提出用一阶自回归误差预测 一阶差分&#xff0c;类似于ResNet的残差思路&#xff1f;记为pred&#xff0c;最终的预测结果

解决PicGo上传图片失败错误信息和上传图片失败包404错误以及Typora怎么一键导入本地图片到PicGo

&#x1f600;前言 解决PicGo上传图片失败错误信息和上传图片失败包404错误以及Typora怎么一键导入本地图片到PicGo &#x1f3e0;个人主页&#xff1a;尘觉主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&#xff0c;希望我的文章可以帮助到大家&#x…

beego通过gorm访问mysql数据库

一、下载golang 二、解压下载包到C盘 三、配置golang系统环境变量 四、进入新建的工作目录C:\project下载并安装beego 五、将新生成的bee.exe所在的路径c:\project\bin加入到系统变量path里面 六、下载并安装mysql 例如在上图中&#xff0c; 选“No thanks,just start my down…

【unity之IMGUI实践】单例模式管理数据存储【二】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

自动化运维工具—Ansible概述

Ansible是什么&#xff1f; Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。 Ansible能批量配置、部署、…

无涯教程-jQuery - Dropable移动函数

Drop-able 功能可与JqueryUI中的交互一起使用。此功能可在任何DOM元素上启用可放置功能。 Drop able - 语法 $( "#droppable" ).droppable(); Drop able - 示例 以下是一个简单的示例&#xff0c;显示了drop-able的用法- <html><head><title>…

爬虫小白-如何调试列表页链接与详情链接不一样并三种方式js逆向解决AES-ECB

目录 一、网站分析二、定位监听三、熟悉AES-ECB四、调试分析五、node运行js六、Python执行js 一、网站分析 三年前的案例&#xff0c;我的原始文章网站 &#xff0c;如图我们直接点击标题进入到详情页&#xff0c;链接会发生跳转&#xff0c;且与我们在详情看到的链接&#xf…

左神算法之中级提升班(8)

目录 【案例1】 【题目描述】 【思路解析】 【代码实现】 【案例2】 【题目描述】 【思路解析】 【代码实现】 【案例3】 【题目描述】 【思路解析】 【案例4】 【题目描述】 【思路解析】 【代码实现】 【案例5】 【题目描述】 【子序列概念】 【思路解析1 经典…

[NLP]LLaMA与LLamMA2解读

摘要 Meta最近提出了LLaMA(开放和高效的基础语言模型)模型参数包括从7B到65B等多个版本。最值得注意的是&#xff0c;LLaMA-13B的性能优于GPT-3&#xff0c;而体积却小了10倍以上&#xff0c;LLaMA-65B与Chinchilla-70B和PaLM-540B具有竞争性。 一、引言 一般而言&#xff0…

020 - STM32学习笔记 - Fatfs文件系统(二) - 移植与测试

020 - STM32学习笔记 - Fatfs文件系统&#xff08;二&#xff09; - 移植与测试 上节学习了FatFs文件系统的相关知识&#xff0c;这节内容继续学习在STM32上如何移植FatFs文件系统&#xff0c;并且实现文件的创建、读、写与删除等功能。各位看官觉得还行的话点点赞&#xff0c…

Python时间处理:探索time模块

日常工作中&#xff0c;经常涉及到一些时间的转换操作&#xff0c;比如某些业务针对时间的操作要转成不同的时区&#xff0c;有的要转换格式入库&#xff0c;有的需要跟时间对比等等&#xff0c;接下来我们一起来看一下python里面是怎么去处理时间的。 time模块简单介绍 Python…