protobuf的序列化和反序列化的分析

一, protobuf的optional 数据类型序列化分析

1,optional 的protobuf的文件 格式

syntax = "proto2";

message test_proto
{
	optional int32 			proto1 			= 1;  
	optional int32          proto2 = 2; 
	optional int32          proto3 = 3;
	optional int32          proto4 = 4; 
	optional uint32          proto5 = 5; 
	optional string          proto6 = 6; 
	optional int32          proto7 = 7; 
	optional int32          proto8 = 8; 

}

测试程序

/***********************************************************************************************
 * 	created: 		2020-04-12
 * 		
 * 	author:			chensong
 * 								
 * 	purpose:		acceptor
 * 	我可能会遇到很多的人,听他们讲好2多的故事,我来写成故事或编成歌,用我学来的各种乐器演奏它。
 * 	然后还可能在一个国家遇到一个心仪我的姑娘,她可能会被我帅气的外表捕获,又会被我深邃的内涵吸引,在某个下雨的夜晚,她会全身淋透然后要在我狭小的住处换身上的湿衣服。
 * 	3小时候后她告诉我她其实是这个国家的公主,她愿意向父皇求婚。我不得已告诉她我是穿越而来的男主角,我始终要回到自己的世界。
 * 	然后我的身影慢慢消失,我看到她眼里的泪水,心里却没有任何痛苦,我才知道,原来我的心被丢掉了,我游历全世界的原因,就是要找回自己的本心。
 * 	于是我开始有意寻找各种各样失去心的人,我变成一块砖头,一颗树,一滴水,一朵白云,去听大家为什么会失去自己的本心。
 * 	我发现,刚出生的宝宝,本心还在,慢慢的,他们的本心就会消失,收到了各种黑暗之光的侵蚀。
 * 	从一次争论,到嫉妒和悲愤,还有委屈和痛苦,我看到一只只无形的手,把他们的本心扯碎,蒙蔽,偷走,再也回不到主人都身边。
 * 	我叫他本心猎手。他可能是和宇宙同在的级别 但是我并不害怕,我仔细回忆自己平淡的一生 寻找本心猎手的痕迹。
 * 	沿着自己的回忆,一个个的场景忽闪而过,最后发现,我的本心,在我写代码的时候,会回来。
 * 	安静,淡然,代码就是我的一切,写代码就是我本心回归的最好方式,我还没找到本心猎手,但我相信,顺着这个线索,我一定能顺藤摸瓜,把他揪出来。
 * 	************************************************************************************************/
#include <iostream>
#include "test.pb.h"

static const char HEX[16] = {
			'0', '1', '2', '3',
			'4', '5', '6', '7',
			'8', '9', 'a', 'b',
			'c', 'd', 'e', 'f'
		};
std::string get_hex_str(const void *_buf, int num)
		{
			std::string str;
			str.reserve(num << 1);
			const unsigned char* buf = (const unsigned char*)_buf;

			unsigned char tmp;
			for (int i = 0; i < num; ++i)
			{
				tmp = buf[i];
				str.append(1, HEX[tmp / 16]);
				str.append(1, HEX[tmp % 16]);
			}
			return str;
		}


void test_msg()
{
	test_proto msg;
	msg.set_proto1(1);
	msg.set_proto2(1);
	msg.set_proto3(1);
	msg.set_proto4(1);
	msg.set_proto5(1);
	msg.set_proto6("c");
	msg.set_proto7(1);
	msg.set_proto8(1);

	std::string temp = msg.SerializeAsString();

	printf("[hex=%s]\n", get_hex_str(temp.c_str(), temp.length()).c_str());
	printf("temp = %s, len = %lu\n" , temp.c_str(), temp.length());
}


int main(int argc, char *argv[])
{
	
	test_msg();
	return 0;
}

运行效果图

在这里插入图片描述

2. 分析protobuf序列化后hex码(16进制)

序列化的后的hex码

0801100118012001280132016338014001

解析:

08:标志第一个的数据
01:第一个数据是1
10:第二个数据
01:第二个数据是1
18:第三个数据
01:第三个数据是1
20:第四个数据
01:第四个数据是1
28:第五个数据
01:第五个数据是1
32:第六个数据(这个标志位是增加10标志是string类型的数据)
01:第六个数据的长度1字节
63:第六个数据是’c’
38:第七个数据(int类型的数据标志位是增加6)
01:第七个数据是1
40:第八个数据
01:第八个数据是1

总结:protobuf的序列化对改变数据类型时增加标志位的是不同的

二, protobuf的repeated 数据类型序列化分析

1, repeated 的protobuf的文件 格式

syntax = "proto2";

message test_proto
{
	optional int32 			proto1 			= 1;   
	repeated int32          proto2 			= 2; 
	optional int32 			proto3 			= 3;
	repeated int32          proto4 			= 4; 
}

测试程序

/***********************************************************************************************
 * 	created: 		2020-04-21
 * 		
 * 	author:			chensong
 * 								
 * 	purpose:		optional
 * 	我可能会遇到很多的人,听他们讲好2多的故事,我来写成故事或编成歌,用我学来的各种乐器演奏它。
 * 	然后还可能在一个国家遇到一个心仪我的姑娘,她可能会被我帅气的外表捕获,又会被我深邃的内涵吸引,在某个下雨的夜晚,她会全身淋透然后要在我狭小的住处换身上的湿衣服。
 * 	3小时候后她告诉我她其实是这个国家的公主,她愿意向父皇求婚。我不得已告诉她我是穿越而来的男主角,我始终要回到自己的世界。
 * 	然后我的身影慢慢消失,我看到她眼里的泪水,心里却没有任何痛苦,我才知道,原来我的心被丢掉了,我游历全世界的原因,就是要找回自己的本心。
 * 	于是我开始有意寻找各种各样失去心的人,我变成一块砖头,一颗树,一滴水,一朵白云,去听大家为什么会失去自己的本心。
 * 	我发现,刚出生的宝宝,本心还在,慢慢的,他们的本心就会消失,收到了各种黑暗之光的侵蚀。
 * 	从一次争论,到嫉妒和悲愤,还有委屈和痛苦,我看到一只只无形的手,把他们的本心扯碎,蒙蔽,偷走,再也回不到主人都身边。
 * 	我叫他本心猎手。他可能是和宇宙同在的级别 但是我并不害怕,我仔细回忆自己平淡的一生 寻找本心猎手的痕迹。
 * 	沿着自己的回忆,一个个的场景忽闪而过,最后发现,我的本心,在我写代码的时候,会回来。
 * 	安静,淡然,代码就是我的一切,写代码就是我本心回归的最好方式,我还没找到本心猎手,但我相信,顺着这个线索,我一定能顺藤摸瓜,把他揪出来。
 * 	************************************************************************************************/

#include "test.pb.h"
#include <iostream>

static const char HEX[16] = {
			'0', '1', '2', '3',
			'4', '5', '6', '7',
			'8', '9', 'a', 'b',
			'c', 'd', 'e', 'f'
		};
std::string get_hex_str(const void *_buf, int num)
		{
			std::string str;
			str.reserve(num << 1);
			const unsigned char* buf = (const unsigned char*)_buf;

			unsigned char tmp;
			for (int i = 0; i < num; ++i)
			{
				tmp = buf[i];
				str.append(1, HEX[tmp / 16]);
				str.append(1, HEX[tmp % 16]);
			}
			return str;
		}


void test_msg()
{
	test_proto msg;
	msg.set_proto1(1);
	for (int i = 0; i < 5; ++i)
	{
		msg.add_proto2(i+10);	
	}
	msg.set_proto3(2);
	for (int i = 0; i < 5; ++i)
	{
		msg.add_proto4(i+10);	
	}

	
	std::string temp = msg.SerializeAsString();

	printf("[hex=%s]\n", get_hex_str(temp.c_str(), temp.length()).c_str());
	printf("temp = %s, len = %lu\n" , temp.c_str(), temp.length());
	
	
	
	//	序列化的后的hex码

//     0801 100a 100b 100c 100d 100e 1802 200a200b200c200d200e
//     
//     解析:
//     
//     08:标志第一个的数据
//     01:第一个数据是1
//     10:第二个数据(10 这里的 10 和地下的10相同表示是 repeated类型的数据 下面10出现次数就是repeated类型数据的个数)
//     0a:第二个数据是10
//     10:第三个数据
//     0b:第三个数据是11
//     10:第四个数据
//     0c:第四个数据是12
//     10:第五个数据
//     0d:第五个数据是13
//     10:第六个数据
//     0e:第六个数据的长度1字节
//     18:第七个数据(int类型的数据标志位是增加6 因为 上面的repeated 类型数据出现的5次使用 是 8 +(5 * 2) = 18)
//     01:第七个数据是2
//     20:第八个数据(20 这里的 20 和地下的20相同表示是 repeated类型的数据 下面20出现次数就是repeated类型数据的个数)
//     0a:第八个数据是10 底下类似的
//     ...........
//     
//     总结:protobuf的序列化对repeated数据类型的个数是不改变标志位的计算个数
	
	
}


int main(int argc, char *argv[])
{
	
	test_msg();
	return 0;
}

运行效果图

在这里插入图片描述

2. 分析protobuf序列化后hex码(16进制)

序列化的后的hex码

0801 100a 100b 100c 100d 100e 1802 200a200b200c200d200e

解析:

08:标志第一个的数据
01:第一个数据是1
10:第二个数据(10 这里的 10 和地下的10相同表示是 repeated类型的数据 下面10出现次数就是repeated类型数据的个数)
0a:第二个数据是10
10:第三个数据
0b:第三个数据是11
10:第四个数据
0c:第四个数据是12
10:第五个数据
0d:第五个数据是13
10:第六个数据
0e:第六个数据的长度1字节
18:第七个数据(int类型的数据标志位是增加6 因为 上面的repeated 类型数据出现的5次使用 是 8 +(5 * 2) = 18)
01:第七个数据是2
20:第八个数据(20 这里的 20 和地下的20相同表示是 repeated类型的数据 下面20出现次数就是repeated类型数据的个数)
0a:第八个数据是10 底下类似的

总结:protobuf的序列化对repeated数据类型的个数是不改变标志位的计算个数

protobuf的序列化测试的代码的地址

猜你喜欢

转载自blog.csdn.net/Poisx/article/details/105463829