序列化与反序列化的本质

1. 将对象存储到本地

假如有一个student类,我们定义了好几个对象,想要把这些对象存储下来,该怎么办呢

from typing import List
class Student:name: strage: intphones: List[str]
s1 = Student("xiaoming",10,["huawei","xiaomi"])

一个极其简单的想法是把这些对象的值拼接到一起编程字符串存储下来,字段与字段之间使用逗号隔开,list的字段则使用#号隔开,想要使用什么字符自己定,只要约定好即可

# xiaoming,10,huawei#xiaomires = ','.join(s1.name,s1.age,'#'.join(s1.phones))
with open('s1.txt','w') as f:f.write(res)

读取这个字符串后按照我们的约定再反解析出来每个字段

with open('s1.txt','r') as f:res = f.read()name,age,phones = res.split(',')
phones = phones.split('#')s1 = Student(name, age, phones)

这样我们就又可以得到这个对象了。

存储数据的过程就是序列化,解析数据的过程就是反序列化

2. 字符串编码

我们把对象转换成字符串存到了本地文件中,并且可以打开这个文件看到我们的字符串。一切好像都很自然。其实中间存在了一个小gap,我们知道计算机只认识二进制,为啥存储的时候没有变成bytes,反而可以是字符串呢?我们把open函数补全一点儿

with open('s1.txt','w',encoding='utf-8') as f:f.write(res)

可以看到多了一个encoding的参数,就是使用utf-8的方式把这段字符串编码成二进制数据。

计算机只认识二进制,要想传输一个对象,必须将其转换成二进制格式。英文有26个字符,还有一些常用的符号,一个想当然的方法就是让每个字符对应一个数字,这就是ASCII码表,例如

二进制十进制十六进制图形
0010 00003220(空格)(␠)
0010 00013321!
0100 00016541A
0110 00019761a

英文是解决了,中文呢?日文呢?俄文呢?为了把所有的文本统一,搞出了一个unicode码本,每个文本都对应了一个二进制。unicode使用4个字节表示一个字符,这对于英文来说就非常的浪费内存,英国人跟英国人交流基本都是英文,他们浏览网站看到的也基本是英文,同样对于中文来说也一样。所以就提出了utf-8的【编码方式】,utf-8是一种变长编码方式,对于英文来说只需要一个字节就可以了,中文只需要3个字节。

在这里插入图片描述

这里需要注意的是,utf-8是一种unicode的编码方式,打个比方,每个人的手机号都是11位的,但是如果你办了亲情网,只需要3位就可以标识自己的老公,老婆,父母了。11位的手机号相当于unicode,可以表示全国所有的人,而亲情网则可以认为是utf-8编码,得到的那3位就是utf-8编码后的号码。

  • 通过unicode码本可以把字符映射成unicode二进制
  • 通过utf-8编码,可以把unicode二进制转换成更短的二进制

我就想,为啥不直接使用utf-8作为码本呢

所以不要觉得是我们把字符串写到本地了,其实这个字符串通过utf-8编码已经变成二进制存储到本地了。
也不要觉得我们直接打开的是字符串,其实通过notepad打开的是二进制,只不过notepad给我们使用utf-8解码了。将这个二进制重新映射成了unicode,通过unicode找到对应的字符给我们显示了出来。

编码转换

使用统一的unicode编码后,每个人看到的就不会是乱码了,俄文日文都可以在我们的电脑上正确的展示出来了。utf-8需要3个字节表示一个中文,但其实只需要2个字节就可以了,utf-8对中文而言也是有点浪费了,所以提出了gbk编码,只需要2个字节来表示中文。引文只是对中文进行编码,如果想要显示俄文那么就会是乱码。
我们请求网页的时候都会告知这个网页的编码方式,一般都是utf-8的,这样兼容性很好,任意字符都可以显示,也有gbk编码的。

如果一个文本使用utf-8编码,使用gbk格式打开就会乱码,同样,如果使用gbk编码,使用utf-8就会乱码。我们可以先使用对应的编码方式打开,这样得到其实就是unicode码,然后再使用想要的编码方式去保存。

这么说来的话,unicode算是一种事实标准了

4. json序列化

回过头来,我们把对象转换成字符串存储到了本地,也可以根据存储的规则反推出原来的对象,这个过程称之为序列化和反序列化,用逗号分隔的格式一般称为csv。更多会使用json格式来进行序列化。

import json
from typing import Listclass Phone:name: strtime: strclass Student:name: strage: intphones: List[Phone]
p1 = Phone("xiaomi", "2024")
p2 = Phone("huawei", "2008")
s1 = Student("xiaoming",10,[p1, p2])res = {}res['name'] = s1.name
res['age'] = s1.age
res['phones'] = [{'name':"xiaomi",'time':"2024"},{'name':"huawei",'time':"2008"}]res_str = json.dumps(res) # 把对象转换成字符串with open('s1.txt','w') as f:f.write(res_str)with open('s1.txt','r') as f:obj = json.loads(f.read())s2 = Student()
s2.name = obj['name']
s2.age = obj['age']
phones2 = []
for phone in obj['phones']:phones2.appen(Phone(phone.name,phone.time))
s2.phones = phones2
  1. 首先把对象转换成json支持的类型,json支持list,tuple,dict,int,str等基础类型
  2. 通过json的dumps函数我们可以把对象转换成字符串,并写到本地

proto序列化

protobuf本质就是一个【数据结构】,例如下面定义一个student的pb文件

syntax = "proto2";
package tutorial;message Phone{optional string name = 1;optional string time = 2;	
}message Student {optional string name = 1;optional int32 age = 2;repeated Phone phones = 3;
}

message可以认为就是class,repeated其实就是list
同样

  1. 将原始对象转成pb格式的对象
  2. 使用seriral序列化函数转换成字符串,并写入到本地

2. proto生成相应的类

proto文件最终通过proto会生产相应的类文件,如果是c++的话就是student.pb.cc和student.pb.h。

protoc --proto_path=. --cpp_out=. ./student.proto

如果是python则是student_pb2.py。

protoc --proto_path=. --python_out=. ./student.proto

proto_path是搜索proto的路径,而cpp_out是生产.cc和.h的路径,最后则是我们的proto路径。在这里的相对路径是相对于protoc执行的路径而言的,哪里执行命令,哪里就是工作路径。
例如proto文件存储在/a/b/test/addressbook.proto,执行protoc的路径是/c/d,此时proto_path和cpp_out使用的相对路径都是相对于/c/d而言的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/384300.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是护网?2024护网行动怎么参加?一文详解_护网具体是做啥的

前言 最近的全国护网可谓是正在火热的进行中,有很多网安小白以及准大一网安的同学在后台问我,到底什么是护网啊?怎么参加呢?有没有相关的学习资料呢?在下不才,连夜整理出来了这篇护网详解文章,希…

逆向案例二十九——某品威客登录,请求头参数加密,简单webpack

网址:登录- 一品威客网,创新型知识技能共享服务平台 抓到登陆包分析,发现请求头有参数加密,直接搜索 定位到加密位置,打上断点,很明显是对象f的a方法进行了加密。 往上找f,可以发现f被定义了,是…

【netty系列-05】深入理解直接内存与零拷贝

Netty系列整体栏目 内容链接地址【一】深入理解网络通信基本原理和tcp/ip协议https://zhenghuisheng.blog.csdn.net/article/details/136359640【二】深入理解Socket本质和BIOhttps://zhenghuisheng.blog.csdn.net/article/details/136549478【三】深入理解NIO的基本原理和底层…

Spring MVC 应用分层

1. 类名使⽤⼤驼峰⻛格,但以下情形例外:DO/BO/DTO/VO/AO 2. ⽅法名、参数名、成员变量、局部变量统⼀使⽤⼩驼峰⻛格 3. 包名统⼀使⽤⼩写,点分隔符之间有且仅有⼀个⾃然语义的英语单词. 常⻅命名命名⻛格介绍 ⼤驼峰: 所有单词⾸字⺟…

探索Linux-1-虚拟机远程登陆XShell6远程传输文件Xftp6

Linux是什么? Linux是一个开源的操作系统内核,由林纳斯托瓦兹(Linus Torvalds)于1991年首次发布。它基于Unix操作系统,但提供了更多的自由和灵活性。Linux内核是操作系统的核心部分,负责管理系统资源、处理…

CSS:position属性

一、属性值 1.1 fixed 固定位置的元素,相对于浏览器窗口进行定位。 元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。 网站中的固定 header 和 footer 就是用固定定位来实现的; header效果图 footer效果图 1.2 absol…

inxedu 因酷教育软件环境搭建

1 地址下载网校系统_考试系统_培训系统_直播教学系统_在线教育系统源码-因酷教育软件-北京因酷时代科技有限公司 2 在idea上的部署环境 解压后用idea打开 maven设置 java编辑器配置 将jdk设置为1.7 tomcat选择为7配置 数据库配置 修改cms上链接数据库的密码 修改端口 运行cms

可能是最好的工具网站

前些苏音在刷视频,发现了一堆好用的宝藏网站,这就赶快分享给大家。 工具网站 这个网站类似于网址导航,集合了包括工具类、资源类、软件类、AI类的合集 并且站长表示励志做体验感最好的工具网,聚焦最快解决用户的需求 首先就是办…

微信自动回复

微信自动回复 文章目录 微信自动回复自动回复步骤微信展开在微信消息区进行监测将微信聊天区截图回复信息实现多次回复(封装函数) 结语 嗨!收到一张超级美丽的风景图,愿你每天都能顺心! 我们这里主要使用pyautogui库&a…

百日筑基第二十八天-23种设计模式-行为型总汇

百日筑基第二十八天-23种设计模式-行为型总汇 文章目录 百日筑基第二十八天-23种设计模式-行为型总汇前言模板方法模式简介模板方式的特点模板方法模式结构类图模板方式模式案例分析模板方法模式应用源码分析模板方法模式的注意事项和细节 迭代器模式迭代器模式结构类图迭代器模…

MySQL 约束 (constraint)

文章目录 约束(constraint)列级约束和表级约束给约束起名字(constraint)非空约束(no null)检查约束(check)唯一性约束 (unique)主键约束 (primary key)主键分类单一主键复合主键主键自增 (auto_increment) 外键约束外什…

cpp程序设计实践,类实现树链刨分以及计算几何类

程序设计要求 是某个cq高校期末程序设计实践作业,全部自己做的比较小众分值90。  试建立一个继承结构,以栈、队列为派生类,建立它们的抽象基类-Bag类,写出各个类的声明及定义,并实现如下功能:  统一命名…

C++基础知识:函数重载相关注意事项:1.引用作为重载条件,2.2.函数重载遇见函数默认参数。

1.引用作为重载条件 #include<iostream>using namespace std;//1.引用作为重载的条件 //int 和 const int 类型不同&#xff0c;所以可以作用重载条件 void fn(int &a) //int &a10;不合法 //10放在了常量区&#xff0c;而引用要么在栈区&#xff0c;要么在堆区{…

【Python】sqlite加密库pysqlcipher3编译安装步骤

目录 说明准备工作openssl编译sqlitetcl setup.py修改quote_argumentopenssl路径 安装加密示例代码测试附录参考 说明 pysqlcipher3是针对Python 3使用的pysqlcipher的一个分支&#xff0c; 尽管仍然维护对Python 2的支持。它仍然处于测试阶段&#xff0c; 尽管这个库包含的最…

网络安全常见错误及解决办法(更新中)

# 开启代理&#xff0c;无法连接网络 把代理关掉 # 上一秒还在安装tree&#xff0c;下一秒xshell就连接不上了 —》sshd服务的key这个文件权限过高&#xff0c;跟装tree没有关系&#xff0c;装一个epel 源&#xff0c;epel-release​ 部分命令&#xff1a;chmod 600 /etc/ssh…

pikauchu之Unsafe Fileupload(不安全的文件上传)

Client check&#xff08;客户检查&#xff09; 第一步先新建一个一句话木马 <?php eval($_POST[1]);?> 然后上传文件 有限制&#xff0c;只能上传那几种类型 现在看看源代码 我们将一句话木马文件的后缀改为png 然后用burp抓包&#xff0c;将png改成php 就能上传成功 …

Android Studio导入源码

在有源码并且编译环境可用的情况下&#xff1a; 1.生成导入AS所需的配置文件 在源码的根目录执行以下命令&#xff1a; source build/ensetup.sh lunch 要编译的项目 make idegen //这一步会生成out/host/linux-x86/framework/idegen.jar development/tools/idegen/idegen.sh…

Spring Boot集成canal快速入门demo

1.什么是canal&#xff1f; canal 是阿里开源的一款 MySQL 数据库增量日志解析工具&#xff0c;提供增量数据订阅和消费。 工作原理 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志&#xff08;binary log&#xff09;, 日志中的记录叫做二进制日志事件&#xff…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十七章 Linux中断实验

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

Spring AI (三) 提示词对象Prompt

3.提示词对象Prompt 3.1.Prompt Prompt类的作用是创建结构化提示词, 实现了ModelRequest<List<Message>>接口 Prompt(String contents)&#xff1a;创建一个包含指定内容的Prompt对象。 Prompt(String contents, ChatOptions modelOptions)&#xff1a;创建一个…