【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电梯楼层数字识别》编写代码,代码整洁,规则,易读。 学习与应…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...