1. 什麼是序列化?
在編寫應用程序的時候往往需要將某些數據存儲在內存中,然後將其寫入某個文件或將它傳輸到網絡中的另一臺計算機上以實現通訊。這個將程序數據轉化成能被存儲並傳輸的格式的過程被稱爲“序列化”(Serialization),而它的逆過程則可被稱爲“反序列化” (Deserialization)。
簡單來說,序列化就是將對象實例轉換爲可存儲或傳輸的數據流的過程。與序列化相對的是反序列化,它根據流重構對象。這兩個過程結合起來,可以輕鬆地存儲和傳輸數據。例如,可以序列化一個對象,然後使用 HTTP 通過 Internet 在客戶端和服務器之間傳輸該對象。
總結
序列化:將對象變成字節流的形式傳出去。
反序列化:從字節流恢復成原來的對象。
2. Google Protocol Buffers(protobuf)
Google Protocol Buffers (GPB)是Google內部使用的數據編碼方式,旨在用來代替XML進行數據交換。可用於數據序列化與反序列化。主要特性有:
- 高效
- 語言中立(Cpp, Java, Python)
- 可擴展
3. protobuf
在使用過程中要注意兩個問題:
(1)支持的數據類型不是很豐富
protobuf屬於輕量級的,因此不能支持太多的數據類型,下面是protobuf支持的基本類型列表,一般需求都能滿足。
.proto type |
c++ |
notes |
double |
double |
|
float |
float |
|
int32 |
int32 |
使用可變長編碼方式,負數時不夠高效,應該使用sint32 |
int64 |
int64 |
同上 |
uint32 |
uint32 |
使用可變長編碼方式 |
uint64 |
uint64 |
同上 |
sint32 |
int32 |
使用可變長編碼方式,有符號的整型值,編碼時比通常的int32高效 |
sint64 |
sint64 |
同上 |
fixed32 |
uint32 |
總是4個字節,如果數值總是比2^28大的話,這個類型會比uint32高效 |
fixed64 |
uint64 |
總是8個字節,如果數值總是比2^56大的話,這個類型會比uint64高效 |
sfixed32 |
int32 |
總是4個字節 |
sfixed64 |
int64 |
總是8個字節 |
bool |
bool |
|
string |
string |
一個字符串必須是utf-8編碼或者7-bit的ascii編碼的文本 |
bytes |
string |
可能包含任意順序的字節數據 |
(2)不支持二維數組(指針),不支持STL容器序列化
稍複雜點的數據結構或類結構裏出現二維數組、二維指針和STL容器(set、list、map等)很頻繁,但因爲 protobuf簡單的實現機制,只支持一維數組和指針(用repeated修飾符修飾),不能使用repeated repeated來支持二維數組, 也不支持STL。
(3)protobuf嵌套後會改變類名稱
protobuf支持類的嵌套,即在一個自定義類型中可以定義另一個自定義類型,但注意嵌套的自定義類型在經過protobuf處理後生成的類名稱並不是你定義的類名稱,而是加上了外層的類名稱作爲前綴,下面舉一個簡單的例子:
message DFA {
required int32 _size = 1;
message accept_pair {
required bool is_accept_state = 1;
required bool is_strict_end = 2;
optional string app_name = 3;
}
repeated accept_pair accept_states = 2;
}
那麼嵌套中的accept_pair 生成後的類不是accept_pair 而是DFA_accept_pair 。如果不想改類名稱,將accept_pair 拿到外面與DFA平行定義即可。