当前位置: 首页 > news >正文

IO流(4)- 序列化流与反序列化流

目录

1. 序列化流与反序列化流的基本介绍

2. 序列化流的基本用法? 

3. 序列化流的作用?

4. 反序列化流的基本用法?

5. 反序列化流的作用

6. 序列化流与反序列化流使用时需要注意的细节(非常重要)

6.1  被序列化的JavaBean类必须实现 Serializable 接口,

6.2 javaBean类尽量在定义时加上"版本号"

6.3 transient 关键字的使用

6.4 序列化流得到的文件不要修改


1. 序列化流与反序列化流的基本介绍

如上图所示,序列化流与反序列化流也是IO流中会用到的一种高级流,也是用来包装基本流对象的,它们的继承关系如上图中所示。

序列化流是字节流的一种,它负责输出数据。

反序列化流也是字节流的一种,它负责输入数据。

2. 序列化流的基本用法? 

如下图所示为序列化流的构造器,序列化流也是一个高级流,它的参数需要传递一个基本流对象;

序列化流地写方法也很简单,名为writeObject(),参数需要传递一个对象,如下所示;

 我来简单给大家演示一下它的使用

(1)既然它是用来写对象的,我们就先创建一个JavaBean类,如下我定义了一个银行账户类

// 这里面要记住,一定要记得实现 Serializable 接口,否则会序列化失败
public class Account implements Serializable {// 账户idprivate Integer accountId;// 账户人名称private String accountName;// 账户密码private String accountPassword;@Overridepublic String toString() {return "Account{" +"accountId=" + accountId +", accountName='" + accountName + '\'' +", accountPassword='" + accountPassword + '\'' +'}';}public Integer getAccountId() {return accountId;}public void setAccountId(Integer accountId) {this.accountId = accountId;}public String getAccountName() {return accountName;}public void setAccountName(String accountName) {this.accountName = accountName;}public String getAccountPassword() {return accountPassword;}public void setAccountPassword(String accountPassword) {this.accountPassword = accountPassword;}
}

接着我们来到另一个测试类,创建一个 main 方法,测试序列化流的使用,我把注释也标注进去

public static void main(String[] args) {// 定义一个账户对象并赋予初始值Account account = new Account(101,"张三","123456");// 创建一个 ObjectOutputStream 的流对象ObjectOutputStream oos = null;try {// 对 oos 赋值// 将 account 的而对象的结果写道 account.txt 文件中去oos = new ObjectOutputStream(new FileOutputStream("user-service/account.txt"));// 将 account 对象写出oos.writeObject(account);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {// 保证给程序的健壮性,关闭之前先做判空操作,否则会空指针异常try {if (oos != null)oos.close();} catch (IOException e) {e.printStackTrace();}}}

我们运行此main 方法,在项目目录下会得到名为 account.txt 的文件,里面就存放着我们 account 对象的信息,我们打开查阅如下所示

可以看到,我们打开所看到的是一大堆乱码,这是为什么呢?

其实这是正常现象,序列化流可以把Java文件写到本地文件中去通常情况下,写到本地文件的系列化流文件我们都是看不懂的,因为这本来就不是给我们看的,而是用于给程序看的。下面我们就此来引出序列化流的作用。

3. 序列化流的作用?

通过刚才的一个小例子,我们简单了解了序列化流的使用,也留下了一个问题。既然写出的文件看不懂,我们要他来做什么用呢?

怎么说呢,我举个最简单的例子,假如你电脑上有一个单机游戏,比如植物大战僵尸吧,大家不知道玩过没有,里面就有金币对吧,当我们不想玩了之后,关闭游戏游戏是会把我们的金币数额和所有的通关进度通过IO流的方式写到我们的本地磁盘上去的,当我们再次打开要玩的时候,它会再次读取到本地文件中的内容,将我们的金币数额和通关进度在读到内存中,我们就可以接着上次的进度游玩了。

游戏将金币数额与游戏进度保存的这个过程,就和序列化很相似;

游戏会将金币数额和游戏进度再次读取到内存中去,就和反序列化有些相似。

那么现在就有一个问题了,如果你是这个游戏的设计者,你在序列化的时候,序列化的得到的游戏进度文件希望玩家能看懂能修改吗?肯定不能吧,如果任意玩家都可以看得懂并且能修改序列化得到的游戏进度文件,那和开外挂有什么区别?我直接把金币改成9999999999,不用再打金币了。

这样举例子各位应该就有些明白了吧!

这也只是序列化流的用途之一,序列化流与反序列化流的用途还有很多,比如互联网传输用户数据,我们通常都是采用二进制传输,你总不能将数据原样进行传输吧,特别是如果传输的数据带有敏感信息,比如账户名称密码,银行账户密码,这些是绝对不能让用户看得懂可以修改的。一旦被不法人员拦截攻击,造成的损失会非常大,因此就可以使用我们的序列化流,将要传输的数据进行序列化处理。

4. 反序列化流的基本用法?

如上图所示,即为反序列化流的构造方法与常用方法,我们来简单的测试一下吧

如下代码,我们把刚才序列化的 account 对象在反序列化回来,我们试一试

public static void main(String[] args) {// 定义一个账户对象并赋予初始值Account account = new Account(101,"张三","123456");// 创建一个 ObjectOutputStream 的流对象ObjectInputStream ois = null;try {// 对 ois 赋值// 将 account.txt 文件中保存的对象数据再读出来ois = new ObjectInputStream(new FileInputStream("user-service/account.txt"));// 将 account 对象读出Object o = ois.readObject();// 输出独到的 account 对象数据System.out.println(o);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {// 保证给程序的健壮性,关闭之前先做判空操作,否则会空指针异常try {if (ois != null)ois.close();} catch (IOException e) {e.printStackTrace();}}}

 运行 main 方法,就可以得到如下图所示的结果

可以看到,原本我们创建的对象 account 就又被我们读取出来了,而且还能还得懂。

5. 反序列化流的作用

通过刚才的演示与对序列化流作用的说明,这里就不需要我在多做解释了,总而言之就一句话。

反序列化流可以将序列化的数据载读取为我们可以看的懂可以操作的原本模样。

6. 序列化流与反序列化流使用时需要注意的细节(非常重要)

6.1  被序列化的JavaBean类必须实现 Serializable 接口,

我们可以来看一下 Serializable 接口的源码,如下所示

可以看到,再序列化流接口中,没有任何东西,这种借口有一个专业名词,被称为标记型接口,备有实际含义,只是作为一个标记,只有被标记的JavaBean类才能参与序列化。如果不实现该接口,就会报错,这里应该也不用多解释,各位在做 Spring 项目的时候,通常都会在javaBean类中是实现 Serializable 接口,因为我们项目运行时的数据就是在互联网之间进行传输的,所以需要实现 Serializable 接口。

6.2 javaBean类尽量在定义时加上"版本号"

有些小伙伴可能不知道,当你对一个JavaBean类添加了 Serializable 接口要参与序列化时,该JavaBean类是有版本号的,如果你对javaBean类做了修改,版本号也会修改,一旦版本号修改,再序列化与反序列化时,就会出现错误,因此我们最好在JavaBean类中添加上版本号,这个我们可以借鉴 ArrayList 的源码设计哦,我们来看一下

在ArrayList 源码中我们可以发现,它也定义了一个版本号,而且各位要注意,这个版本号变量不是乱起的,必须是 serialVersionUID,不能是别的;如果不添加 serialVersionUID 变量,我们的javaBean类一旦发生修改,版本号也会修改,就是因为版本号不一致导致无法序列化成功,因此我们需要让版本号使用为一个,就需要定义为 final,又因为它是该类属性中共享属性,需要定义为 static ,serialVersionUID 最好定义为 long 类型。

因此,在定义版本号时,最好定义为

private static final long serialVersionUID = ?

至于取什么值,无所谓,只要遵守该变量的定义原则即可。

6.3 transient 关键字的使用

还有一些时候,我们不想让JavaBean 类中的一些变量参与序列化与反序列化,该怎么办呢?

这个时候就可以用到我们的 transient 关键字。

被 transient 关键字修饰的变量,不会参与到类的序列化与反序列化,我来给大家演示一下,还拿刚才的例子举例说明,如下图所示

我把 accountpassword 账户密码这一属性不参与数列化,因为太不安全,我们就可以在JavaBean类中 该变量前面加上 transient 关键字,一旦加上,就不会参与序列化,我们再回到 main 方法作出修改

public static void main(String[] args) {// 定义一个账户对象并赋予初始值Account account = new Account(101,"张三","123456");// 创建一个 ObjectOutputStream 的流对象ObjectOutputStream oos = null;// 创建一个 ObjectOutputStream 的流对象ObjectInputStream ois = null;try {// 对 oos 赋值oos = new ObjectOutputStream(new FileOutputStream("user-service/account.txt"));// 对 ois 赋值// 将 account.txt 文件中保存的对象数据再读出来ois = new ObjectInputStream(new FileInputStream("user-service/account.txt"));// 先将 account 对象写出oos.writeObject(account);// 再将 account 对象读出Object o = ois.readObject();// 输出独到的 account 对象数据System.out.println(o);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {// 保证给程序的健壮性,关闭之前先做判空操作,否则会空指针异常try {if (oos != null)oos.close();if (ois != null)ois.close();} catch (IOException e) {e.printStackTrace();}}}

 然后再次运行得到如下结果

可以发现,即便我们初始为 accountPassword 赋值,但因为添加了 transient 关键字的缘故,他就不会参与序列化与反序列化,系统胡自动给一个默认值为 null。

各位小伙伴有些时候再看源码时的时候可能也见过 transient 关键字,就是用来做标记的,不让其被标记的变量参与序列化。

6.4 序列化流得到的文件不要修改

我们在通过序列化得到的文件,虽然是一堆乱码看不懂,但时不要轻易去修改,因为一旦修改,再次反序列化时,程序就读不出来了,会报错,这也是序列化流中需要注意的一个点哦!

相关文章:

IO流(4)- 序列化流与反序列化流

目录 1. 序列化流与反序列化流的基本介绍 2. 序列化流的基本用法? 3. 序列化流的作用? 4. 反序列化流的基本用法? 5. 反序列化流的作用 6. 序列化流与反序列化流使用时需要注意的细节(非常重要) 6.1 被序列化的…...

人工智能如何应对 DevOps 监控和可观测性挑战

自 ChatGPT 横空出世之后,AIGC 已成为不可逆转的时代浪潮。在之前的文章中,我们介绍了DevOps 领域中AI的用例,需要回顾可以点击下方链接。在本篇文章中,我将简单聊聊人工智能(AI)如何通过分析日志和指标来预…...

数字化新时代,VR全景拍摄与制作

导语: 随着科技的飞速发展,数字化图片正在引领新的时代潮流。在这个数字化图片的新时代,VR全景拍摄与制作技术正以其独特的特点和无限的优势,成为数字影像领域的一颗璀璨明星。让我们深入了解VR全景拍摄与制作的特点和优势&#…...

uniapp 权限说明

android.permission.ACCESS_CHECKIN_PROPERTIES 访问登记属性 读取或写入登记check-in数据库属性表的权限 android.permission.ACCESS_COARSE_LOCATION 获取错略位置 通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米 android.permission.ACCESS…...

3D Web轻量化渲染开发工具HOOPS Communicator是什么?

HOOPS Communicator是Tech Soft 3D旗下的主流产品之一,具有强大的、专用的高性能图形内核,是一款专注于基于Web端的高级3D工程应用程序。由HOOPS Server和HOOPS Web Viewer两大部分组成,提供了HOOPS Convertrer、Data Authoring的模型转换和编…...

心法利器[93] | 谈校招:技术面

心法利器 本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。 2022年新一版的文章合集已经发布,累计已经60w字了,获取方式看这里&…...

excel英语翻译让你的数据更容易被理解

从前有一个名叫小明的办公室职员,他每天都要处理大量的数据和报表。然而,由于工作需要,他经常收到来自不同国家的Excel表格,这些表格上的内容都是用各种各样的语言编写的,让他很难理解其中的意思。这时,小明…...

RK3588S之CPU--benchmark(二)

目录 一、引言 二、benchmark测试工具 ------>2.1、Geekbench ------------>2.1.1、下载移植 ------------>2.1.2、跑分结果 ------------>2.1.3、跑分榜 ------>2.2、Spec06 ------------>2.2.1、spec06介绍 ------------>2.2.2、下载移植(包含…...

入侵检查基础

一、结合以下问题对当天内容进行总结 1. 什么是IDS? 2. IDS和防火墙有什么不同? 3. IDS工作原理? 4. IDS的主要检测方法有哪些详细说明? 5. IDS的部署方式有哪些? 6. IDS的签名是什么意思?签名过滤器有什么…...

JAVA开发工具-maven的安装与配置(最新最详细教程)

引言 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具 软件。 Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较 高的可重用性,所以常常用两…...

linux系统编程重点复习--进程的控制

目录 1 复习目标 2 进程相关概念 2.2 并行和并发 2.3 PCB-进程控制块 2.4 进程状态(面试考) 3 创建进程 3.2 ps命令和kill命令 3.3 getpid/getppid 3.4 练习题 4 exec函数族 4.1 函数作用和函数介绍 4.1.1 execl函数 4.1.2 execlp函数 4.2 exec函数族原理介绍 4.3 …...

12-1_Qt 5.9 C++开发指南_自定义插件和库-自定义Widget组件(提升法(promotion)创建自定义定制化组件)

当UI设计器提供的界面组件不满足实际设计需求时,可以从 QWidget 继承自定义界面组件。 有两种方法使用自定义界面组件: 一种是提升法(promotion),例如在8.3 节将一个QGraphicsView组件提升为自定义的 QWGraphicsView 类,提升法用…...

【软件测试学习】—软件测试的基本认识(一)

【软件测试学习】—软件测试的基本认识(一) 文章目录 【软件测试学习】—软件测试的基本认识(一)一、什么是软件测试二、软件测试的目的三、测试的原则四、测试的标准五、测试的基本要求六、bug的由来七、测试的流程八、开发模式九…...

Unity AI项目笔记

一、创建虚拟环境 在开始进行Unity AI项目之前,首先需要设置一个适当的虚拟环境。以下步骤将会指导你如何创建: 下载Python 3.7。下载Anaconda 2020.11。可以在清华大学开源软件镜像站找到镜像资源:https://mirrors.tuna.tsinghua.edu.cn/a…...

如何在地图上寻找峨眉山零公里的龙洞湖

爬峨眉山的需要,住在零公里附近。 据说这附近有个好玩的地方叫龙洞湖,我们住得远,想步行去看看。拿出地图,搜龙洞湖,尴尬了。搜不到具体位置。细想,人家整个村就叫龙洞村,地图上居然没有标识&a…...

cloudstack平台host加入后,显示CPU speed为0GHz

一、环境说明 操作系统:openEuler 22.03CPU:Kunpeng-920,arm v8cloudstack:4.18libvirtd:6.2.0 二、问题描述 cloudstack平台初始化完成后,第一次加入host,系统虚拟机一直无法正常创建&#…...

创新技术应用,提升企业图文档管理水平的新思路

信息爆炸和数字化发展的时代,企业图文档管理显得尤为重要。传统的纸质文件管理方式已经无法满足企业高效、安全、便捷管理的需求。因此,创新技术的应用成为了提升企业图文档管理水平的必然选择。PDM(产品数据管理)与BOM&#xff0…...

网络安全 Day22-mariadb数据库用户管理

数据库用户管理 1. mariadb数据库用户管理2. mariadb数据库用户授权3. 用户回收授权4. 使客户端连接数据库 1. mariadb数据库用户管理 用户的格式: 用户主机范围 合起来才算一个用户授权主机范围 只能从本机访问: localhost或127.0.0.1或10.0.0.166(指定IP)授权整个网段: 授权…...

SERDES关键技术

目录 一、SERDES介绍 二、SERDES关键技术 2.1 多重相位技术 2.2 线路编解码技术 2.2.1 8B/10B编解码 2.2.2 控制字符(Control Characters) 2.2.3 Comma检测 2.2.4 扰码(Scrambling) 2.2.5 4B/5B与64B/66B编解码技术 2.3 包传…...

小程序如何上传商品图片

了解如何在小程序商城中上传商品图片是非常重要的,因为商品图片的质量和展示效果直接影响到用户对商品的购买决策。下面,我将介绍怎么在小程序上传产品图片的方法和注意事项。 1. 图片准备:在上传商品图片之前,首先要准备好商品图…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​,覆盖应用全生命周期测试需求,主要提供五大核心能力: ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络&#xf…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...