C++ 序列化和反序列化學習

定義

  • 程序員在編寫應用程序的時候往往需要將程序的某些數據存儲在內存中,然后將其寫入某個文件或是將它傳輸到網絡中的另一臺計算機上以實現通訊。這些過程將會涉及到程序數據轉化成能被存儲并傳輸的格式,因此被稱為“序列化”(Serialization),而它的逆過程則可被稱為“反序列化” (Deserialization)
  • 簡單來說,序列化就是將對象實例的狀態轉換為可保持或傳輸的格式的過程。與序列化相對的是反序列化,它根據流重構對象。這兩個過程結合起來,可以輕松地存儲和傳輸數據。例如,可以序列化一個對象,然后使用 HTTP 通過 Internet 在客戶端和服務器之間傳輸該對象。

總結

  • 序列化:將對象變成字節流的形式傳出去。
  • 反序列化:從字節流恢復成原來的對象。

序列化的好處

  • 將對象存儲于硬盤上 ?,便于以后反序列化使用
  • 在網絡上傳送對象的字節序列時便捷性、靈活性

C++對象序列化的四種方法

JSON文本序列化方式

  • 使用jsoncpp或cJSON等庫,將內存中的數據結構序列化為JSON格式的文本串。

Google Protocol Buffers(protobuf)(推薦)

目的

  • Google Protocol Buffers (GPB)是Google內部使用的數據編碼方式,旨在用來代替XML進行數據交換。可用于數據序列化與反序列化。主要特性有:高效;語言中立;可擴展
  • 官方文檔
  • github地址
  • 參考示例

Boost.Serialization(推薦)

目的

  • Boost.Serialization可以創建或重建程序中的等效結構,并保存為二進制數據、文本數據、XML或者有用戶自定義的其他文件。該庫具有以下吸引人的特性: 代碼可移植(實現僅依賴于ANSI C++);深度指針保存與恢復;可以序列化STL容器和其他常用模版庫;數據可移植;非入侵性。

MFC Serialization (不推薦)

目的

  • Windows平臺下可使用MFC中的序列化方法。MFC 對 CObject 類中的序列化提供內置支持。因此,所有從 CObject 派生的類都可利用 CObject 的序列化協議

.Net Framework (不推薦)

目的

  • .NET的運行時環境用來支持用戶定義類型的流化的機制。它在此過程中,先將對象的公共字段和私有字段以及類的名稱(包括類所在的程序集)轉換為字節流,然后再把字節流寫入數據流。在隨后對對象進行反序列化時,將創建出與原對象完全相同的副本。

簡單總結

  • 其中MFC和.Net框架的方法適用范圍很窄,只適用于Windows下,且.Net框架方法還需要.Net的運行環境
  • 參考分析
  • Google Protocol Buffers效率較高,但是數據對象必須預先定義,并使用protoc編譯,適合要求效率,允許自定義類型的內部場合使用。
  • Boost.Serialization 使用靈活簡單,而且支持標準C++容器。
  • 相比而言,MFC的效率較低,但是結合MSVS平臺使用最為方便。
  • 為了考慮平臺的移植性、適用性和高效性,推薦大家使用Google的protobuf和Boost的序列化方案,下面介紹我使用這兩種方案的心得及注意事項。

進一步學習

Google Protocol Buffers

  • Google Protocol Buffers protobuf相對而言效率應該是最高的,不管是安裝效率還是使用效率,protobuf都很高效,而且protobuf不僅用于C++序列化,還可用于Java和Python的序列化,使用范圍很廣。

protobuf支持的數據類型不是很豐富

  • 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

可能包含任意順序的字節數據

protobuf不支持二維數組(指針),不支持STL容器序列化

  • 這個缺陷挺大,因為稍復雜點的數據結構或類結構里出現二維數組、二維指針和STL容器(set、list、map等)很頻繁,但因為 protobuf簡單的實現機制,只支持一維數組和指針(用repeated修飾符修飾),不能使用repeated repeated來支持二維數組, 也不支持STL,因此在選擇該方案之前,一定 要確保你的數據結構里沒有這些不支持的類型。

protobuf嵌套后會改變類名稱

  • protobuf支持類的嵌套,即在一個自定義類型中可以定義另一個自定義類型,但注意嵌套的自定義類型在經過protobuf處理后生成的類名稱并不是你定義的類名稱,而是加上了外層的類名稱作為前綴

Boost.Serialization

  • Boost庫是個很龐大的庫,功能非常豐富,序列化只是其中的一個小分支,但為了使用Boost的序列化方案,你需要安裝整個Boost庫,所花費的磁盤空間和時間都很多,同樣支持的序列化功能也很強大,既支持二維數組(指針),也支持STL容器,更不需要我們用某種特殊的格式重新定義我們的類結構,其非侵入的性質使得我們無須改動已有的類結構即可序列化,這時非常贊的一個性質。
  • 但是由于體積龐大,安裝復雜,如果只是簡單的序列化,沒必要使用該方案,只有protobuf不能滿足你的需求時,才應該考慮該方案。
  • 安裝boost庫遇到的一系列問題 安裝boost庫本事就是一項很費時的工程,如果期間出現了各種錯誤,更加耗時耗耐心。
  • 對于基本類型指針很難序列化
  • 不能序列化變長數組

參考代碼

  • C++ 序列化探索
  • 1)對基本數據類型char,short,int,long,string的序列化;
  • 2)支持序列化為socket流;
  • 3)支持對std::vector、std::list、std::set、std::map的序列化;

參考鏈接

  • 最常用的兩種C++序列化方案的使用心得(protobuf和boost serialization)

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/447011.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447011.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447011.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android設計模式之——觀察者模式

一、介紹 觀察者模式是一個使用率非常高的模式,它最常用的地方是GUI系統、訂閱——發布系統。因為這個模式的一個重要作用就是解耦,將被觀察者和觀察者解耦,使得它們之間的依賴性更小,甚至做到毫無依賴。以GUI系統來說&#xff0…

Android設計模式之——備忘錄模式

一、介紹 備忘錄模式是一種行為模式,該模式用于保存對象當前狀態,并且在之后可以再次恢復到此狀態,這有點像我們平時說的”后悔藥“。備忘錄模式實現的方式需要保證被保存的對象狀態不能被對象從外部訪問,目的是為了保護好被保存…

c++ memory 頭文件詳細介紹

類 指針特征 pointer_traits (C11) 提供關于指針式類型的信息 (類模板) 垃圾收集器支持 pointer_safety (C11) 列出指針安全模式 (枚舉) 分配器 allocator 默認的分配器 (類模板) allocator_traits (C11) 提供關于分配器類型的信息 (類模板) allocator_arg_t (C11) 標簽類型…

C++ using的三種使用策略以及具體的用法

Using的使用方法 1,命名空間的使用 為了防止代碼沖突,都會使用到命名空間。假設這樣一種情況,當一個班上有兩個名叫 Zara 的學生時,為了明確區分他們,我們在使用名字之外,不得不使用一些額外的信息&#…

Android設計模式之——迭代器模式

一、介紹 迭代器模式(Iterator Pattern)又稱為游標(Cursor)模式,是行為型設計模式之一。迭代器模式算是一個比較古老的設計模式,其源于對容器的訪問,比如Java中的List、Map、數組等&#xff0c…

Android設計模式之——模板方法模式

一、介紹 在面向對象開發過程中,通常會遇到這樣的一個問題,我們知道一個算法所需的關鍵步驟,并確定了這些步驟的執行順序,但是,某些步驟的具體實現是未知的,或者說某些步驟的實現是會隨著環境的變化而改變…

Android設計模式之——訪問者模式

一、介紹 訪問者模式是一種將數據操作與數據結構分離的設計模式,它是《設計模式》中23種設計模式中最復雜的一個,但它的使用頻率并不高,正如《設計模式》的作者GOF對訪問者模式的描述:大多數情況下,你不需要使用訪問者…

C++類模板template <class T>簡單使用方法

一個簡單的例子 兩個數比大小 如果兩個數都是int類型 class Compare_int { public :Compare(int a,int b){xa;yb;}int max( ){return (x>y)?x:y;}int min( ){return (x<y)?x:y;} private :int x,y; }; 如果兩個數是float類型 class Compare_float { public :Compare(…

Android設計模式之——中介者模式

一、介紹 中介者模式&#xff08;Mediator Pattern&#xff09;也稱為調解者模式或調停者模式&#xff0c;Mediator本身就有調停者和調解者的意思。 在日常生活中調停者或調解者這個角色我們見得比較多的是“和事老”&#xff0c;也就是說調解兩個有爭端的人的角色&#xff0…

C++智能指針中unique_ptr部分內容的講解

參考鏈接 std::unique_ptr 介紹 定義位于頭文件<memory>std::unique_ptr 是通過指針占有并管理另一對象&#xff0c;并在 unique_ptr 離開作用域時釋放該對象的智能指針。 在下列兩者之一發生時用關聯的刪除器釋放對象&#xff1a;1&#xff0c;銷毀了管理的 unique_pt…

Java基礎——Java多線程中sleep()、wait()和notify()

一、sleep()sleep()方法源碼&#xff1a;/** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does …

Key_handle的學習

代碼 一切盡在不言中 #pragma once#include "common/common.h" #include "sdf/sdf.h"#include <memory>namespace sdf {namespace algorithm {class KeyHandle {public:using erased_internal_data_t char; //使用erased_internal_data_t等效于ch…

Java基礎——虛擬機結構

一、Java平臺結構圖二、JVM、JRE和JDK關系JVM&#xff1a;Java Virtual Machine&#xff08;Java虛擬機&#xff09;&#xff0c;負責執行符合規范的Class文件 JRE&#xff1a; Java Runtime Environment &#xff08;java運行環境&#xff09;&#xff0c;包含JVM和類庫 JDK&a…

解決 SSH Connection closed by foreign host 問題

用 Xshell 連接服務器總是報錯 : Connection closed by foreign host.Disconnected from remote host... 原因可能是 SSH 服務器沒設置保活時間間隔 , 具體設置如下 : 操作 # vim /etc/ssh/sshd_config 添加兩行 , 或去掉注釋 : ClientAliveInterval 60ClientAliveCountMax…

Java基礎——synchronized

synchronized重要&#xff01;重要&#xff01;重要&#xff01;重要的事情說三遍&#xff0c;一定要記下來哦。 Java語言的關鍵字&#xff0c;當它用來修飾一個方法或者一個代碼塊的時候&#xff0c;能夠保證在同一時刻最多只有一個線程執行該段代碼。一、當兩個并發線程訪問同…

C++:MAC安裝Boost庫文件并且使用CLion開發

boost的filestem庫 C在17版本的標準庫中引入了一個filesystem庫&#xff0c;用來處理文件路徑&#xff0c;以及文件訪問。很多編譯器對filesystem庫的支持還不是很好。為了解決這個問題&#xff0c;可以臨時使用boost::filesystem來替代。其實C17標準中的filesystem庫就是從bo…

Java基礎——Java異常處理機制

一、引言 try…catch…finally恐怕是大家再熟悉不過的語句了&#xff0c;而且感覺用起來也是很簡單&#xff0c;邏輯上似乎也是很容易理解。不過&#xff0c;我親自體驗的“教訓”告訴我&#xff0c;這個東西可不是想象中的那么簡單、聽話。不信&#xff1f;那你看看下面的代碼…

clion在使用sqlite3的時候,顯示Undefined symbols for architecture x86_64錯誤的解決辦法

顯示Undefined symbols for architecture x86_64錯誤的原因 1、缺少靜態庫 環境&#xff1a;在模擬器上報錯但在真機上能運行成功&#xff0c;而且報的錯誤來自于第三方庫。原因&#xff1a;architecture x86_64 是指模擬器的架構&#xff0c;意思就是 Crypto 變量在模擬器架…

Java基礎——Java反射機制及IoC原理

一、概念 主要是指程序可以訪問&#xff0c;檢測和修改它本身狀態或行為的一種能力&#xff0c;并能根據自身行為的狀態和結果&#xff0c;調整或修改應用所描述行為的狀態和相關的語義。在java中&#xff0c;只要給定類的名字&#xff0c; 那么就可以通過反射機制來獲得類的所…

Ubuntu boost庫文件安裝編譯

簡單介紹 Boost庫是為C語言標準庫提供擴展的一些C程序庫的總稱&#xff0c;由Boost社區組織開發、維護.Boost向來有準標準庫之稱&#xff0c;很多新特性例如智能指針等都是先在boost中實現&#xff0c;后來被吸收到標準庫之中. Boost實現了日志、算法、日期、地理、數學、線程…