亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

protobuf簡介及使用流程

 更新時間:2025年02月26日 14:13:44   作者:不如小布.  
本文介紹了Protocol Buffers(protobuf)的數(shù)據(jù)結構序列化和反序列化框架,包括其特點、使用流程和快速上手,通過一個簡單的通訊錄示例,展示了如何創(chuàng)建.proto文件、添加注釋、編寫消息定義、編譯.proto文件以及進行序列化和反序列化操作,感興趣的朋友一起看看吧

1. Protobuf是什么

  ProtoBuf(全稱Protocol Buffer)是數(shù)據(jù)結構序列化和反序列化框架,它具有以下特點:

  • 語??關、平臺無關:即 ProtoBuf ?持 Java、C++、Python 等多種語?,?持多個平臺
  • ?效:即? XML 更小、更快、更為簡單
  • 擴展性、兼容性好:你可以更新數(shù)據(jù)結構,而不影響和破壞原有的舊程序

2. Protobuf使?流程介紹

  • 編寫 .proto ?件,?的是為了定義結構對象(message)及屬性內容。
  • 使? protoc 編譯器編譯 .proto ?件,?成?系列接?代碼,存放在新?成頭?件和源?件中。
  • 依賴?成的接?,將編譯?成的頭?件包含進我們的代碼中,實現(xiàn)對 .proto ?件中定義的字段進行設置和獲取,和對 message 對象進行序列化和反序列化

3. ProtoBuf快速上手

  我們以?個簡單通訊錄的實現(xiàn)來驅動對Protobuf的學習。在通訊錄demo中,我們將實現(xiàn):

  • 對?個聯(lián)系?的信息使? Protobuf 進?序列化,并將結果打印出來。
  • 對序列化后的內容使? Protobuf 進?反序列,解析出聯(lián)系?信息并打印出來。
  • 聯(lián)系?包含以下信息: 姓名、年齡。

  通過通訊錄demo,我們能快速的了解ProtoBuf的使?流程。

3.1 創(chuàng)建 .proto ?件

  • 創(chuàng)建 .proto ?件時,?件命名應該使?全?寫字?命名,多個字?之間? _ 連接。 例如:lower_snake_case.proto
  • 書寫 .proto ?件代碼時,應使? 2 個空格的縮進。

  我們?yōu)橥ㄓ嶄?demo 新建?件: contacts.proto

3.2 添加注釋

  向?件添加注釋,可使? // 或者 /* … */

3.3 具體編寫

  指定 proto3 語法:
  Protocol Buffers 語?版本3,簡稱 proto3,是 .proto ?件最新的語法版本。proto3 簡化了 ProtocolBuffers 語?,既易于使?,?可以在更?泛的編程語?中使?。它允許你使? Java,C++,Python等多種語??成 protocol buffer 代碼。在 .proto ?件中,要使? syntax = “proto3”; 來指定?件語法為 proto3,并且必須寫在除去注釋內容的第??。 如果沒有指定,編譯器會使?proto2語法。
  在通訊錄 demo 的 contacts.proto ?件中,可以為?件指定 proto3 語法,內容如下:

syntax = "proto3";

   package 聲明符:
   package 是?個可選的聲明符,能表? .proto ?件的命名空間,在項?中要有唯?性。它的作?是為了避免我們定義的消息出現(xiàn)沖突。
   在通訊錄 demo 的 contacts.proto ?件中,可以聲明其命名空間,內容如下:

package contacts;

   定義消息(message):
  消息(message): 要定義的結構化對象,我們可以給這個結構化對象中定義其對應的屬性內容。在網(wǎng)絡傳輸中,我們需要為傳輸雙?定制協(xié)議。定制協(xié)議說?了就是定義結構體或者結構化數(shù)據(jù),?如,tcp,udp 報?就是結構化的。再?如將數(shù)據(jù)持久化存儲到數(shù)據(jù)庫時,會將?系列元數(shù)據(jù)統(tǒng)??對象組織起來,再進?存儲。ProtoBuf 就是以 message 的方式來?持我們定制協(xié)議字段,后期幫助我們形成類和?法來使用。
  在通訊錄 demo 中我們就需要為聯(lián)系人定義?個 message:

.proto ?件中定義?個消息類型的格式為:

message 消息類型名{
}
消息類型命名規(guī)范:使?駝峰命名法,?字??寫。

為 contacts.proto(通訊錄 demo)新增聯(lián)系?message

syntax = "proto3";
package contacts;
// 定義聯(lián)系?消息
message PeopleInfo {
}

  定義消息字段:
  在 message 中我們可以定義其屬性字段,字段定義格式為:字段類型 字段名 = 字段唯?編號;

  • 字段名稱命名規(guī)范:全?寫字?,多個字?之間? _ 連接。
  • 字段類型分為:標量數(shù)據(jù)類型 和 特殊類型(包括枚舉、其他消息類型等)。
  • 字段唯?編號:?來標識字段,?旦開始使?就不能夠再改變。

  樣例:

// 聲明語法版本
syntax = "proto3";
// 聲明代碼的命名空間
package contacts;
//結構化對象的描述
message PeopleInfo{
    // 各個字段描述:   字段類型  字段名 = 字段唯一編號
    string name = 1;
    int32 age = 2;
}

  注:這?還要特別講解?下字段唯?編號的范圍:1 ~ 536,870,911 (2^29 - 1) ,其中 19000 ~ 19999 不可?。
  19000 ~ 19999 不可?是因為:在 Protobuf 協(xié)議的實現(xiàn)中,對這些數(shù)進?了預留。如果?要在.proto?件中使?這些預留標識號,例如將 name 字段的編號設置為19000,編譯時就會報警。
  值得?提的是,范圍為 1 ~ 15 的字段編號需要?個字節(jié)進?編碼, 16 ~ 2047 內的數(shù)字需要兩個字節(jié)進?編碼。編碼后的字節(jié)不僅只包含了編號,還包含了字段類型。所以 1 ~ 15 要?來標記出現(xiàn)?常頻繁的字段,要為將來有可能添加的、頻繁出現(xiàn)的字段預留?些出來。

3.4 編譯 contacts.proto 文件

  編譯命令?格式為:

protoc [--proto_path=IMPORT_PATH] --cpp_out=DST_DIR path/to/file.proto
protoc             是 Protocol Buffer 提供的命令?編譯?具。
--proto_path       指定被編譯的.proto?件所在?錄,可多次指定??珊唽懗?-I IMPORT_PATH 。如不指
                   定該參數(shù),則在當前?錄進?搜索。當某個.proto ?件 import 其他.proto ?件時,
                   或需要編譯的 .proto ?件不在當前?錄下,這時就要?-I來指定搜索?錄。
--cpp_out=         指編譯后的?件為 C++ ?件。
OUT_DIR            編譯后?成?件的?標路徑。
path/to/file.proto 要編譯的.proto?件

  編譯 contacts.proto ?件命令如下:

protoc --cpp_out=. contacts.proto

  編譯 contacts.proto ?件后,會?成所選擇語?的代碼,我們選擇的是C++,所以編譯后?成了兩個文件: contacts.pb.h contacts.pb.cc 。
  對于編譯?成的 C++ 代碼,包含了以下內容 :

  • 對于每個 message ,都會?成?個對應的消息類
  • 在消息類中,編譯器為每個字段提供了獲取和設置?法,以及?下其他能夠操作字段的方法
  • 編輯器會針對于每個 .proto ?件?成 .h 和 .cc ?件,分別?來存放類的聲明與類的實現(xiàn)

  contacts.pb.h 部分代碼展示:

class PeopleInfo final : public ::PROTOBUF_NAMESPACE_ID::Message {
public:
	 using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom;
	 void CopyFrom(const PeopleInfo& from);
	 using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom;
	 void MergeFrom( const PeopleInfo& from) {
	 PeopleInfo::MergeImpl(*this, from);
 }
 static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
	 return "PeopleInfo";
 }
	 // string name = 1;
	 void clear_name();
	 const std::string& name() const;
	 template <typename ArgT0 = const std::string&, typename... ArgT>
	 void set_name(ArgT0&& arg0, ArgT... args);
	 std::string* mutable_name();
	 PROTOBUF_NODISCARD std::string* release_name();
	 void set_allocated_name(std::string* name);
	 // int32 age = 2;
	 void clear_age();
	 int32_t age() const;
	 void set_age(int32_t value);
};

  上述的例?中:

  • 每個字段都有設置和獲取的方法, getter 的名稱與?寫字段完全相同,setter ?法以 set_ 開頭。
  • 每個字段都有?個 clear_ 方法,可以將字段重新設置回 empty 狀態(tài)。

  contacts.pb.cc 中的代碼就是對類聲明?法的?些實現(xiàn),在這?就不展開了。
  到這?有人可能就有疑惑了,那之前提到的序列化和反序列化?法在哪?呢?在消息類的?類MessageLite 中,提供了讀寫消息實例的方法,包括序列化?法和反序列化?法。

class MessageLite {
public:
	//序列化:
	bool SerializeToOstream(ostream* output) const; // 將序列化后數(shù)據(jù)寫??件
	流
	bool SerializeToArray(void *data, int size) const;
	bool SerializeToString(string* output) const;
	//反序列化:
	bool ParseFromIstream(istream* input); // 從流中讀取數(shù)據(jù),再進?反序列化
	動作
	bool ParseFromArray(const void* data, int size);
	bool ParseFromString(const string& data);
};

  注意:

  • 序列化的結果為?進制字節(jié)序列,???本格式。
  • 以上三種序列化的?法沒有本質上的區(qū)別,只是序列化后輸出的格式不同,可以供不同的應?場景使?。
  • 序列化的 API 函數(shù)均為const成員函數(shù),因為序列化不會改變類對象的內容, ?是將序列化的結果保存到函數(shù)?參指定的地址中

  序列化與反序列化的使用:
  創(chuàng)建?個測試?件 test.cc,?法中我們實現(xiàn):

  • 對?個聯(lián)系?的信息使? PB 進?序列化,并將序列化結果打印出來。
  • 對序列化后的內容使? PB 進?反序列,解析出聯(lián)系?信息并打印出來。
#include <iostream>
#include "contacts.pb.h"
using namespace std;
int main()
{
    string people_str;
    {
        contacts::PeopleInfo people;
        people.set_age(20);
        people.set_name("忘憂");
        if(!people.SerializeToString(&people_str))
        {
            cout << "序列化聯(lián)系人失敗" <<endl;
        }
        cout << "序列化之后的 people_str: " << people_str << endl;
        // 反序列化
        {
            contacts::PeopleInfo people;
            if(!people.ParseFromString(people_str))
            {
                cout << "反序列化聯(lián)系人失敗" <<endl;
            }
            cout << "Parse age: " << people.age() << endl;
            cout << "Parse name: " << people.name() << endl;
        }
    }
    return 0;
}

代碼書寫完成后,編譯 test.cc,生成可執(zhí)行程序:

g++ test.cc contacts.pb.cc -o test -std=c++11 -lprotobuf

執(zhí)?可執(zhí)?程序,可以看? people 經(jīng)過序列化和反序列化后的結果:

  由于 ProtoBuf 是把聯(lián)系?對象序列化成了?進制序列,這?? string 來作為接收?進制序列的容器。所以在終端打印的時候會有換?等?些亂碼顯?。另外相對于 xml 和 JSON 來說,因為PB被編碼成?進制,破解成本增?,ProtoBuf 編碼是相對安全的。

到此這篇關于protobuf簡介及使用流程的文章就介紹到這了,更多相關protobuf使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • SpringBoot整合ELK實現(xiàn)日志監(jiān)控

    SpringBoot整合ELK實現(xiàn)日志監(jiān)控

    這篇文章主要為大家詳細介紹了SpringBoot整合ELK實現(xiàn)日志監(jiān)控的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-11-11
  • 詳解mybatis中association和collection的column傳入多個參數(shù)問題

    詳解mybatis中association和collection的column傳入多個參數(shù)問題

    這篇文章主要介紹了詳解mybatis中association和collection的column傳入多個參數(shù)問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-10-10
  • SpringBoot中的異常處理與參數(shù)校驗的方法實現(xiàn)

    SpringBoot中的異常處理與參數(shù)校驗的方法實現(xiàn)

    這篇文章主要介紹了SpringBoot中的異常處理與參數(shù)校驗的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • Spring boot按日切分spring boot的nohup.out日志文件的方法

    Spring boot按日切分spring boot的nohup.out日志文件的方法

    過大的日志文件維護起來存在諸多問題,所以最好是能夠按日或按大小切分日志文件,下面小編給大家?guī)砹薙pring boot按日切分spring boot的nohup.out日志文件的方法,一起看看吧
    2018-08-08
  • Java的字符串中對子字符串的查找方法總結

    Java的字符串中對子字符串的查找方法總結

    這篇文章主要介紹了Java的字符串中對子字符串的查找方法總結,是Java入門學習中的基礎知識,需要的朋友可以參考下
    2015-11-11
  • Java 異常的知識整理

    Java 異常的知識整理

    這篇文章主要介紹了Java 異常的知識整理的相關資料,需要的朋友可以參考下
    2017-07-07
  • XFire構建web service客戶端的五種方式

    XFire構建web service客戶端的五種方式

    本篇文章主要介紹了XFire構建web service客戶端的五種方式。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • Java中json與javaBean幾種互轉的講解

    Java中json與javaBean幾種互轉的講解

    今天小編就為大家分享一篇關于Java中json與javaBean幾種互轉的講解,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • SpringBoot整合easy-es的詳細過程

    SpringBoot整合easy-es的詳細過程

    本文介紹了EasyES,一個基于Elasticsearch的ORM框架,旨在簡化開發(fā)流程并提高效率,EasyES支持SpringBoot框架,并提供了CRUD操作、批量操作和查詢操作等方法,文章還列舉了使用EasyES時可能遇到的技術難題及解決方法,感興趣的朋友一起看看吧
    2025-02-02
  • Java8新特性Stream流中anyMatch和allMatch和noneMatch的區(qū)別解析

    Java8新特性Stream流中anyMatch和allMatch和noneMatch的區(qū)別解析

    這篇文章主要介紹了Java8新特性Stream流中anyMatch和allMatch和noneMatch的區(qū)別解析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01

最新評論