【Java IO流】缓冲流和对象流的解析和应用实例
目录
前言
一、缓冲流
四种方式拷贝文件的用时对比
二、对象流
1. 使用对象流写入对象到本地文件
2. 使用对象流读取对象数据
总结
前言
【File文件管理及IO流(基本流)】
http://t.csdnimg.cn/uG5Ff 该篇博客中,介绍了学习高级流需要的前置知识:
- 文件管理
-
基本的输入输出流:了解基本的输入输出流的概念和使用方法,包括字节流和字符流,以及如何读写文件或处理其他数据源。
Java 中的高级流指的是建立在基本字节流或字符流之上的流,它们提供了更高级别的功能以简化 I/O 操作。除缓冲流和对象流外,常见的高级流还有:数据流、打印流、压缩流、转换流等。
一、缓冲流
缓冲流(Buffered Streams)在 Java 中是一种用于提高输入输出效率的流。它们通过在内存中创建缓冲区来减少对底层资源(如文件、网络连接)的频繁访问,从而提高读写数据的性能。
常见的缓冲流包括:
BufferedInputStream(字节缓冲输入流)BufferedOutputStream(字节缓冲输出流)BufferedReader(字符缓冲输入流)BufferedWriter(字符缓冲输出流)
它们构造方法的参数都是对应的基本流,例如:
public BufferedInputStream(InputStream is)

缓冲流的原理:底层自带了长度为8192的缓冲区提高性能。
缓冲中的两个独有方法(非常实用):
1.readLine() 读取一行 用于从输入流中读取一行文本数据,并返回一个字符串表示该行数据。这个方法通常用于读取文本文件中的内容,逐行读取文本信息。2.newLine() 通用换行 作用是写入一个平台无关的行分隔符,即换行符。 使用 newLine()方法可以根据当前平台自动生成正确的换行符,而不需要手动编写特定的换行符。 通常情况下,不同操作系统的行分隔符如下:(1)Windows 系统使用回车符和换行符表示行尾,即\r\n(2)Unix 和类 Unix 系统(如 Linux)使用换行符表示行尾,即 \n。(3)旧版 Mac OS 使用回车符表示行尾,即 \r。
为方便读取文本文件,这里用字符缓冲流进行示例(需要创建好对应的文件,路径也要正确):

import java.io.*;public class CharacterBS { //字符缓冲流public static void main(String[] args) throws IOException {//读取数据(输入流)BufferedReader br = new BufferedReader(new FileReader("File\\buffer.txt"));//两个独有方法:readLine() 读取一行// newLine() 通用换行String s;while ((s = br.readLine()) != null) {System.out.println(s);}br.close();//写数据(输出流)BufferedWriter bw = new BufferedWriter(new FileWriter("File\\buffer2.txt"));bw.write("缓冲流(Buffered Streams)");bw.newLine();bw.write("BufferedReader:提供缓冲读取文本数据的功能。");bw.newLine();bw.write("BufferedWriter:提供缓冲写入文本数据的功能。");bw.newLine();bw.close();}
}
读取的数据:

写入的数据:

四种方式拷贝文件的用时对比
拷贝文件四种方式拷贝文件(边读边写),并统计各自用时(这里的文件越大越好,太小体现不出差别)1.字节流的基本流:一次读写一个字节2.字节流的基本流:一次读写一个字节数组[8192]3.字节缓冲流:一次读写一个字节4.字节缓冲流:一次读写一个字节数组[8192]
import java.io.*;public class Test1 {public static void main(String[] args) throws IOException {/*拷贝文件四种方式拷贝文件,并统计各自用时字节流的基本流:一次读写一个字节字节流的基本流:一次读写一个字节数组字节缓冲流:一次读写一个字节字节缓冲流:一次读写一个字节数组*/long time1 = method1();long time2 = method2();long time3 = method3();long time4 = method4();System.out.println(time1);System.out.println(time2);System.out.println(time3);System.out.println(time4);}private static long method1() throws IOException {long start = System.currentTimeMillis();FileInputStream fis = new FileInputStream("File\\read.txt");FileOutputStream fos = new FileOutputStream("File\\write.txt");int b;while ((b = fis.read()) != -1) {fos.write(b);}fos.close();fis.close();long end = System.currentTimeMillis();return end - start;}private static long method2() throws IOException {long start = System.currentTimeMillis();FileInputStream fis = new FileInputStream("File\\read.txt");FileOutputStream fos = new FileOutputStream("File\\write.txt");byte[] bytes = new byte[8192];int len;while ((len = fis.read(bytes)) != -1) {fos.write(bytes, 0, len);}fos.close();fis.close();long end = System.currentTimeMillis();return end - start;}private static long method3() throws IOException {long start = System.currentTimeMillis();BufferedInputStream bis = new BufferedInputStream(new FileInputStream("File\\read.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("File\\write.txt"));int b;while ((b = bis.read()) != -1) {bos.write(b);}bos.close();bis.close();long end = System.currentTimeMillis();return end - start;}private static long method4() throws IOException {long start = System.currentTimeMillis();BufferedInputStream bis = new BufferedInputStream(new FileInputStream("File\\read.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("File\\write.txt"));byte[] bytes = new byte[8192];int len;while ((len = bis.read(bytes)) != -1) {bos.write(bytes, 0, len);}bos.close();bis.close();long end = System.currentTimeMillis();return end - start;}
}
对比结果(文件太小了所以读写字节数组的差距没有体现):
- 字节流的基本流:一次读写一个字节
- 字节流的基本流:一次读写一个字节数组[8192]
- 字节缓冲流:一次读写一个字节
- 字节缓冲流:一次读写一个字节数组[8192]

二、对象流
对象流(Object Streams)也叫序列化/反序列化流,是 Java 中用于读写对象的流。对象流可以将对象以二进制形式序列化(Serialization)后写入输出流,也可以从输入流中读取二进制数据并反序列化(Deserialization)为对象。
Java 提供了两个主要的对象流类:
- ObjectOutputStream:用于将对象序列化后写入输出流。
- ObjectInputStream:用于从输入流中读取二进制数据并反序列化为对象。
同缓冲流,它们构造方法的参数也是基本流:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("objects.bin"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("objects.bin"));
需要注意的是,要使对象能够被序列化,该对象所属的类必须实现 Serializable 接口。序列化过程会将对象转换成字节序列,因此对象的字段和类的结构都需要支持序列化。
对象流的使用场景包括但不限于:保存和加载对象数据(因为写入到文件后是一对看不懂的数据)、对象的网络传输等。
作用:通过对象流,我们可以方便地将对象以二进制形式写入到输出流中,并从输入流中读取并还原为对象,实现了对象的持久化和简化了数据传输。写入到文件后
细节:要写出的对象必须实现Serializable接口(标记性接口) + serialVersionUID(版本号)否则会抛出NotSerializableException异常
写入对象的方法:writeObject(对象);
读取对象的方法:readObject(); 返回值:Object
1. 使用对象流写入对象到本地文件
写入对象前的准备工作,自定义类:
import java.io.Serial;
import java.io.Serializable;public class Student implements Serializable {@Serialprivate static final long serialVersionUID = -3931917465211028662L;private String name;private int age;//transient: 瞬态关键字//作用:不会把当前属性序列化到本地文件当中private transient String address;public Student() {}public Student(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}/*** 获取** @return name*/public String getName() {return name;}/*** 设置** @param name*/public void setName(String name) {this.name = name;}/*** 获取** @return age*/public int getAge() {return age;}/*** 设置** @param age*/public void setAge(int age) {this.age = age;}/*** 获取** @return address*/public String getAddress() {return address;}/*** 设置** @param address*/public void setAddress(String address) {this.address = address;}public String toString() {return "Student{name = " + name + ", age = " + age + ", address = " + address + "}";}
}
import java.io.Serial;
import java.io.Serializable;public class Teacher implements Serializable {@Serialprivate static final long serialVersionUID = 2983184546427358899L;private String name;private int age;private String address;public Teacher() {}public Teacher(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}/*** 获取** @return name*/public String getName() {return name;}/*** 设置** @param name*/public void setName(String name) {this.name = name;}/*** 获取** @return age*/public int getAge() {return age;}/*** 设置** @param age*/public void setAge(int age) {this.age = age;}/*** 获取** @return address*/public String getAddress() {return address;}/*** 设置** @param address*/public void setAddress(String address) {this.address = address;}public String toString() {return "Teacher{name = " + name + ", age = " + age + ", address = " + address + "}";}
}
写入一个对象:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;public class Test1 { //序列化流/对象操作输出流public static void main(String[] args) throws IOException {/*需求:利用序列化流/对象操作输出流,把一个对象写到本地文件中细节:要写出的对象必须实现Serializable接口(标记性接口) + serialVersionUID(版本号)否则回抛出NotSerializableException异常transient: 瞬态关键字作用:不会把当前属性序列化到本地文件当中*///1.创建对象Student stu = new Student("张三", 23, "厦门");//2.创建续流化流/对象操作输出流对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("File\\object.txt"));//3.写出对象oos.writeObject(stu);//4.关流oos.close();}
}
写入后的数据:

写入多个对象:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;public class Test_1 {public static void main(String[] args) throws IOException {/*用对象流读写多个对象需求:将多个自定义对象序列化到文件中,但是由于对象的个数不确定,反序列流该如何读取?*///序列化多个对象//1.创建对象Teacher t1 = new Teacher("张三", 23, "北京");Teacher t2 = new Teacher("李四", 24, "上海");Teacher t3 = new Teacher("王五", 25, "深圳");//2.将对象添加到集合中ArrayList<Teacher> list = new ArrayList<>();list.add(t1);list.add(t2);list.add(t3);//3.序列化集合ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("File\\teacher.txt"));oos.writeObject(list);//4.关流oos.close();}
}
2. 使用对象流读取对象数据
读取单个对象:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class Test2 { //反序列化流/对象操作输入流public static void main(String[] args) throws IOException, ClassNotFoundException {//1.创建反序列化流/对象操作输入流ObjectInputStream ois = new ObjectInputStream(new FileInputStream("File\\object.txt"));//2.读取数据Object o = ois.readObject();//3.打印对象System.out.println(o);//4.释放资源ois.close();}
}
运行结果:

读取多个对象:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;public class Test_2 {public static void main(String[] args) throws IOException, ClassNotFoundException {//1.创建反序列化流的对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("File\\teacher.txt"));//2.读取数据ArrayList<Teacher> o = (ArrayList<Teacher>) ois.readObject();//System.out.println(o);for (Teacher teacher : o) {System.out.println(teacher);}//3.关流ois.close();}
}
运行结果:

总结
当涉及到 Java I/O 操作时,缓冲流和对象流是两种非常常用的高级流。
缓冲流的功能:
- 提供了缓冲区功能,可以减少对底层数据源的直接访问次数,从而提高读写效率。
- 适用于对大量数据进行读写操作。
缓冲流的优点:
- 提高了I/O操作的性能,减少了与底层数据源的交互次数。
- 提供了逐行读取文本数据的功能,方便文本处理操作。
对象流的功能:
- 用于将对象序列化成字节流或反序列化为对象。
- 可以实现对象的持久化、网络传输和跨平台数据交换等功能。
对象流的优点:
- 方便实现对象的保存和加载,简化了对象的序列化和反序列化过程。
- 可以实现对象在不同系统之间的传输和共享。
综上所述,缓冲流适用于提高读写效率和处理大量数据,而对象流则适用于处理对象的序列化和反序列化,方便实现对象数据的持久化和传输。根据具体需求,可以选择合适的流来进行数据操作。
相关文章:
【Java IO流】缓冲流和对象流的解析和应用实例
目录 前言 一、缓冲流 四种方式拷贝文件的用时对比 二、对象流 1. 使用对象流写入对象到本地文件 2. 使用对象流读取对象数据 总结 前言 【File文件管理及IO流(基本流)】http://t.csdnimg.cn/uG5Ff 该篇博客中,介绍了学习高级流需要的…...
鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Select)
提供下拉选择菜单,可以让用户在多个选项之间选择。 说明: 该组件从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Select(options: Array<SelectOption>) 参数:…...
mysql将一个表另存为新表,同时复制索引、约束、主键等信息
使用 SHOW CREATE TABLE 语句获取原表的创建语句: SHOW CREATE TABLE 原表名;将 原表名 替换为要复制的原始表的名称。 此语句将返回一个包含原表完整创建语句的结果集。创建语句包括表的结构、列定义、索引、约束、主键等所有信息。 复制结果集中的创建语句&…...
基于springboot+vue的房屋交易平台
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 主要内容:毕业设计(Javaweb项目|小程序|Pyt…...
17个工作必备的Python自动化代码分享(上篇)
引言 Python是一种流行的编程语言,以其简单性和可读性而闻名。因其能够提供大量的库和模块,它成为了自动化各种任务的绝佳选择。让我们进入自动化的世界,探索17个可以简化工作并节省时间精力的Python脚本。 目录(上篇࿰…...
python-0008-修改django数据库为mysql
操作系统 centos7 执行 在虚拟环境中执行: pip3 install mysqlclient2.2.4 -i https://mirrors.aliyun.com/pypi/simple无法安装问题 如果安装mysqlclient时提示找不到对应的版本,或者编译失败,请退出虚拟环境,执行以下操作&…...
oracle用户密码过期
很久不用的项目遇到报错 2024-03-14 11:15:01.806 [Druid-ConnectionPool-Create-110651474] ERROR com.alibaba.druid.pool.DruidDataSource 2879 - create connection SQLException, url: jdbc:oracle:thin://192.168.0.54:1521/orcl, errorCode 28001, state 99999 java.sq…...
安全地使用v-html
vue2 1、 使用插件DOMPurify DOMPurify是一个开源的基于DOM的快速XSS净化工具。输入HTML元素,然后通过DOM解析递归元素节点,进行净化,输出安全的HTML <div v-html"sanitizedContent"></div>import DOMPurify from dompurify; data () {return {htmlCont…...
MongoDB从0到1:高效数据使用方法
MongoDB,作为一种流行的NoSQL数据库。从基础的文档存储到复杂的聚合查询,从索引优化到数据安全都有其独特之处。文末附MongoDB常用命令大全。 目录 1. 引言 MongoDB简介 MongoDB的优势和应用场景 2. 基础篇 安装和配置MongoDB MongoDB基本概念 使…...
Go——运算符,变量和常量,基本类型
一.运算符 Go语言内置的运算符有: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 1.1 算术运算符 注意:(自增)和--(自减)在go语言中是单独的语句,并不是运算符。 1.2 关系运算符 1.3 逻辑运算符 1.4 位运算符 位运算符对整数在内存…...
js使用canvas实现图片鼠标滚轮放大缩小拖拽预览,显示像素坐标,显示像素值
html代码 todo 实现画矩形框,圆形roi <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title&…...
ArrayList 源码解析和设计思路
ArrayList 一、继承体系二、接口继承三、标记接口四、设计目的五、框架总体结构六、工作原理七、创建List对象初始化?还是add()添加元素初始化?七、add(E e)添加元素八、remove(int index)删除元素八、线程安全问题 一、继承体系 ArrayLis…...
Win10系统使用IIS服务搭建WebDAV网站结合内网穿透公网访问本地文件
文章目录 推荐1. 安装IIS必要WebDav组件2. 客户端测试3. cpolar内网穿透3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访问测试 4. 安装Raidrive客户端4.1 连接WebDav服务器4.2 连接成功4.2 连接成功总结: 推荐 前些天发现了一个巨牛的人工智能…...
AWTK 开源串口屏的配置文件
配置文件 每个 HMI 应用程序都需要一个配置文件,用于配置 HMI 的基本信息、服务、持久化、告警信息、历史数据等。 文件位置 design/default/data/settings.json基本配置 name - 名称(必须配置,只能用字母、数字、下划线) se…...
Spring、SpringMVC、Spring Boot常见注解有哪些?不要混淆了哦
Spring、SpringMVC、Spring Boot常见注解 一、Spring 注解说明Component、Controller、Service、Repository使用在类上用于实例化BeanAutowired使用在字段上用于根据类型依赖注入Qualifier结合Autowired一起使用用于根据名称进行依赖注入Scope标注Bean的作用范围Configuratio…...
在notion里面实现四象限清单
四象限清单是一种时间管理工具,旨在帮助人们根据任务的重要性和紧急性来优先排序他们的工作。这个概念最早由德怀特艾森豪威尔提出,后来又被史蒂芬柯维在他的著作《高效能人士的七个习惯》中进一步普及。四象限清单将任务分为四个类别: 第一…...
【linux】搜索所有目录和子目录下的包含.git的文件并删除
一、linux命令搜索所有目录和子目录下的包含.git的文件 在Linux系统中,要搜索所有目录和子目录下的包含.git的文件,可以使用find命令。find命令允许指定路径、表达式和操作来查找文件。 以下是使用find命令搜索包含.git的文件的方法: 1. 基…...
三、传输层拥塞控制、差错控制
3.1 概述和传输层服务 传输服务和协议: 为运行在不同主机上的应用进程提供逻辑通信; 传输协议运行在端系统-发送方:将应用层的报文分成报文段,然后传递给网络层;接收方:将报文段重组成报文,然后传递给应用…...
主流电商平台数据大规模数据采集接口的实现:电商API接口接入方案和电商数据采集现状
现实问题 1、您是否需要经常统计关注的品牌、产品、平台、卖家的电商数据,包括销量、评价量、收藏量、预售量、运费、赠品和促销信息,手头上没有稳定的数据源? 2、您是否经常需要统计授权卖家和非授权卖家的销售、动销占比,分析…...
Python电梯楼层数字识别
程序示例精选 Python电梯楼层数字识别 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对《Python电梯楼层数字识别》编写代码,代码整洁,规则,易读。 学习与应…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...
