【技术类】PB二进制序列化

自从使用protobuf作序列化工具之后,每次面试都问我,为什么用?
很迅速的回答了体积小,解析快。
为什么小,采用了varint的压缩方式,那你讲一下这个压缩方式,然后emmm…
那为什么解析快,有没有跟其他做过对比,又是emmm…

test.proto
syntax = "proto2";

message Test
{
	required int32 first = 1;
	optional int32 second = 2;
	optional string third = 3;
}
这里使用C++语言,编译到当前目录命令: protoc test.proto --cpp_out=./
产生两个文件:test.pb.h	test.pb.cc(动态链接库)
#include <iostream>
#include "test.pb.h"
using namespace std;

int main()
{
	Test st;
	st.set_first(10);
	st.set_second(20);
	st.set_third("hello");
	
	char buffer[64] = {0};
	if(!st.SerializeToArray(buffer,st.ByteSize()))
		cout<<"Serlialize Error"<<endl;
	return 0;
}
//由于序列化的结果中含有0,所以采用gdb调试打印看,结果如下:
$1 = "\b\n\020\024\032\005hello", '\000' <repeats 52 times>
下面的文献内容,摘自大佬的博客,自己只是用来学习,附上地址,如有侵犯,联系本人,会尽快处理。
https://blog.csdn.net/chengzi_comm/article/details/53199278

protobuf的message中每个字段的格式为: 修饰符 字段类型 字段名 = 域号;
在序列化时,protobuf按照TLV的格式序列化每一个字段,T即Tag,也叫Key;L是Value的长度,如果一个字段是整形,这个L部分会省略;V是该字段对应的值value。

序列化后的Value是按原样保存到字符串或者文件中,Key按照一定的转换条件保存起来,序列化后的结果就是 KeyValueKeyValue。

Key的序列化格式是按照message中字段后面的域号与字段类型来转换。转换公式如下:
(field_number << 3) | wire_type,wire_type与字段的类型有关(不同类型采用的压缩方式不一)

比如:int32,int64等采用varint(wire_type=0),string就采用Length-delimi(wire_type=2)
这里只列举这两个,其他的type类型可以去官网查看。

protobuf规定:
1.如果域号在[1,15]范围内,会使用一个字节表示Key;
2.如果域号大于等于16,会使用两个字节表示Key;
3.Key编码过后,该字节的第一个比特位表示之后的一个字节是否与当前这个字节有关:
	a.如果第一个比特位为1,表示有关,即连续两个字节都是Key的编码;
	b.如果第一个比特位为0,表示Key的编码只有当前一个字节,后面的字节是Length或者Value;
计算first
key = (1 << 3) | 0 = 8, 8对应的ASCLL就是‘\b’,因为是int型所以不需要指定长度
那么‘\n’就是value,10喽。

second
key = (2 << 3) | 0 = 16, 16的八进制码是20
24就是value(20)的八进制码了。

third
key = (3 << 3) | 2 = 26,26的八进制码是32,后面的5就是长度,以及后面的内容了

到这里我们只是把数据对应上了,体积小表现在哪?

我们可以清晰的看到10和20两个4字节的数被编码成了一个字节的八进制数。怎么做的。
例: 10的二进制码 = 00000000 00000000 00000000 00001010
	1.从最后字节取7位,如果当前字节后面没字节了,那么就在最高位补1,否则补0。
	2.讲得到的字节拼接起来得到00000000 00000000 00000000 10001010
	3.如果字节表示的数为0,那么舍弃该字节,此时得到的就是10001010
做反序列化工作时:第一位是1,那么剩下7位都是数据,则为0001010 = 10。

如果数据比较大时,那么编码可能会占用两个字节,比如300:10101100 00000010 
解析工作:高位为0,代表这是最后一个字节,1代表还有数据。去掉最高位拼接得到 0000010 0101100
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PB串口是指标准的软硬件串口通信协议,通过该协议可以实现串口数据的传输。在使用PB串口发送二进制数据时,需要按照一定的规则来进行数据的组织和发送。 首先,需要确定发送的二进制数据的格式和长度。二进制数据可以以字节数组的形式表示,每个字节可以表示8位的二进制数据。根据具体的需求,可以确定发送的数据长度,如发送一个字节、多个字节或者数据包。 其次,将发送的二进制数据按照指定的格式进行组织。可以使用编程语言提供的字节操作函数,将需要发送的数据转换为字节数组。将每个字节的二进制数据按照顺序存储在数组中。 然后,将组织好的二进制数据通过PB串口发送出去。可以使用相应的串口通信库或者API函数,打开PB串口,并设置相应的串口参数,如波特率、数据位、停止位等。然后使用发送函数将二进制数据发送出去,可以按照字节的顺序依次发送,也可以将整个数据包一次性发送。 最后,接收端通过相同的PB串口协议接收二进制数据。接收端需要相应的程序来监听串口数据,并按照发送时的数据格式进行解析。可以使用串口通信库提供的接收函数,按照字节的顺序接收数据,并根据具体的需求进行处理。 总之,使用PB串口发送二进制数据需要将数据按照一定的格式组织,并通过相应的串口通信库来实现数据的发送和接收。需要注意的是,在发送和接收过程中需要保持发送端和接收端的串口参数一致,以确保数据的正确传输。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值