当前位置: 首页 > 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. 图片准备:在上传商品图片之前,首先要准备好商品图…...

vue中人员导出功能实现

大纲: 1、导出定义的export.js文件 代码展示 import axios from axios //导出一 export const exportExcel (url, params, name, type post) > {// url url路径 params 查询参数 name 文件名 type 请求方式axios[type](url, params, {responseType: blob,}).t…...

【微信小程序】引入第三方库poke对GZIP压缩数据进行解压

使用 npm 包管理工具: 首先,在小程序的根目录下执行 npm init 初始化项目,生成 package.json 文件。然后,通过 npm 安装 pako:npm install pako。接下来,在小程序的根目录下创建一个名为 miniprogram_npm 的…...

Pandas操作Excel

Pandas 是 Python 语言的一个扩展程序库,用于数据分析。 菜鸟教程:https://www.runoob.com/pandas/pandas-tutorial.html 读取Excel pd.read_excel(path,sheet_name,header) path:excel文件路径sheet_name:读取的sheet&#xff0…...

leetcode 712. Minimum ASCII Delete Sum for Two Strings(字符串删除字母的ASCII码之和)

两个字符串s1, s2, 删除其中的字母使s1和s2相等。 问删除字母的最小ASCII码之和是多少。 思路: DP 先考虑极端的情况,s1为空,那么要想达到s2和s1相等,就要把s2中的字母删完, ASCII码之和就是s2中所有字母的ASCII码之…...

Springboot -- 按照模板生成docx、pdf文件,docx转pdf格式

使用 poi-tl 根据模板生成 word 文件。 使用 xdocreport 将 docx 文件转换为 pdf 文件。 xdocreport 也支持根据模板导出 word ,但是 poi-tl 的功能更齐全,操作更简单,文档清晰。 poi-tl 、xdocreport 内部均依赖了 poi ,要注意两…...

UE5.1.1 创建C++项目失败

因一直使用Unity开发环境,安装Unreal后,并未详细配置过其开发环境,默认创建蓝图工程无异常,但创建UE C项目时总共遇到两个错误: 错误一 Running /Epic/UE/UE_5.1/Engine/Build/BatchFiles/Build.bat -projectfiles -…...

windows进行端口映射

windows进行端口映射 1. 查询端口映射情况 netsh interface portproxy show v4tov42. 查询某一个IP的所有端口映射情况 netsh interface portproxy show v4tov4 | find "[IP]" # 例: netsh interface portproxy show v4tov4 | find "192.168.1.1&quo…...

Python 异常处理

Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误。你可以使用该功能来调试python程序。 异常处理: 本站Python教程会具体介绍。断言(Assertions):本站Python教程会具体介绍。 python标准异常 异常名称描述BaseException所有异常的…...

C++ 类的静态成员

在结构化程序设计中程序模块的基本单位是函数,因此模块间对内存中数据的共享是通过函数与和函数之间的数据共享来实现的,其中包括两个途径——参数传递和全局变量。 面向对象的程序设计方法兼顾数据的共享和保护,将数据与操作数据的函数封装…...

360T7路由器进行WiFi无线中继教程

360T7路由器进行WiFi中继教程 1. 概述2. 360T7路由器进行WiFi中继实现教程2.1 登录路由器管理界面2.2 选择上网方式2.3 搜索WiFi2.4 连接WiFi2.5 点击确认2.6 在主页面查看网络 1. 概述 中继路由系统由一组中继路由器组成,为不能交换路由信息的路由域提供中继路由。…...