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的序列化測試的代碼的地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章