序列化和反序列化

今天看到了一篇关于序列化和反序列化的文章,然后也想说下自己对序列化和反序列化的理解,然后再补充下pb,和xml,json的不同。

1. 什么是序列化?

程序员在编写应用程序的时候往往需要将程序的某些数据存储在连续的内存中,然后将其写入文件或是将其传输到网络中的另一台计算机上以实现通讯。这个将程序数据转换成能被存储并传输的格式的过程被称为序列化(serialization),而它的逆过程被称为反序列化(deserialization)。

  简单来说,序列化就是将对象实例的状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它根据流重构对象。这两个过程结合起来,可以轻松地存储和传输数据。

  序列化:将对象变成字节流的形式传出去,也就是放在连续的内存地址空间中。
  反序列化:从字节流恢复成原来的对象,从连续的内存地址空间恢复成对象。

2. 序列化实现

可以通过将对象转换成json、xml和二进制流的方式实现序列化(这里要注意protobuffer也是采用的二进制形式存储的,但是有自己的编码格式,后面会转载一个链接),json和xml在不同编程语言中其组包、解包的API接口实现方法的不同,而通用的二进制流的方式实现序列化,一般在c/c++编程中我们就是用的memcoy,一般是把一个结构体对象,拷贝到一个char数组里。而protobuffer,也是二进制流的形式,而xml和json是文本的形式,下面我来具体的解释下,什么是文本格式的,什么是二进制格式的。比方说我的json文件是这样的,

{“age”:150},我们要编码一个int 形式的变量,那么json的表示就是左边的这个字符串,而用xml表示,成这个字符串,<age>150</age>,当然我们在传输的时候,肯定都是传的二进制了,我们可以看下,这两个字符串占用多少个字节,json的是,11个字节,xml的是,14个字节,而我们的proto buffer 呢,为什么说他是二进制编码呢,

一个简单的消息

message Test1 {
  required int32 age = 1;
}

我们创建一个Test1消息,给a赋值150,序列化之后存储,我们得到如下的3个byte数据(16进制表示):

08 96 01

首先注意后面那个a=1,中的1可不是给a进行赋值,而是这个变量的唯一标识数字,在传递过程中也不会再传递这个变量名字了,只会传1代表这个变量。我稍微解释下,这三个字节,brotobuffer 是小字节序列,也就是高位在后,01代表的就是,刚才,后的1,08 96两个字节代表的是150.具体的编码规则解释见文章:protobuf的编码方式_ChaoticLife的博客-CSDN博客_protobuf编码方式

然后最后传输的时候,直接传刚才的3个字节就可以了。

我们看下同样一个数据,字节数据对比,json,11个字节,xml,14个字节,pb,3个字节,所以pb肯定省空间啊,自然传输的就快啊,当然也有可读性差等缺点,我会在后面给出来详细的对比图。

这里还有注意一点,我们所谓的把一个对象,转化成json,或者是xml,也是把一个结构体或者是类对象,转化成一个xml,或者是json结构形式的字符串 ,字符串的内部结构也是一个char的数组,所以也是一个连续的内存结构。

这里再添加点个人理解,大家都熟悉的ice里用的slice语言,以及谷歌的grpc里用的protobuffer这些也都是序列化的一个手段,其实序列化的目的就是为了方便传输,以及方便解析,因为我们没法把一个完整的对象通过网络传输到另外一台电脑上。所以出现了序列化和反序列化。

同时采用二进制流的方式我们经常使用的是memcopy函数,拷贝内存,一般情况下,把数据放到一个结构体里,然后将结构体里的数据拷贝到char数组里,这个把结构体对象里的数据,拷贝到char数组,就是拷贝到了连续的内存里,这个就是序列化,这里要特别注意的是  字节对齐,以及浅拷贝的问题,结构体里不能有指针,或者是封装了指针的类对象,像是string,否则就会出错。你想想下你把一个机器的地址,传给另外一个机器,没有任何作用,如果结构体里有指针数据,那么需要你把所有的数据也拷贝出来,也就是要深拷贝。因为我们一般定义协议的时候,肯定都是很清晰的,有帧头,帧尾,各个数据长度,而我们在使用类对象表示数据的时候,可能并不一定都是简单类型,可以里面嵌套指针之类的,我们自己用的时候,在一个进程里,肯定拿着指针,可以进行 解引用的,但是在一个机器的多个进程中,或者多个机器中,肯定是不行的。

3. pb,json,xml对比图

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值