欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

protobuf簡(jiǎn)介及使用流程

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

1. Protobuf是什么

  ProtoBuf(全稱Protocol Buffer)是數(shù)據(jù)結(jié)構(gòu)序列化和反序列化框架,它具有以下特點(diǎn):

  • 語(yǔ)??關(guān)、平臺(tái)無(wú)關(guān):即 ProtoBuf ?持 Java、C++、Python 等多種語(yǔ)?,?持多個(gè)平臺(tái)
  • ?效:即? XML 更小、更快、更為簡(jiǎn)單
  • 擴(kuò)展性、兼容性好:你可以更新數(shù)據(jù)結(jié)構(gòu),而不影響和破壞原有的舊程序

2. Protobuf使?流程介紹

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

3. ProtoBuf快速上手

  我們以?個(gè)簡(jiǎn)單通訊錄的實(shí)現(xiàn)來(lái)驅(qū)動(dòng)對(duì)Protobuf的學(xué)習(xí)。在通訊錄demo中,我們將實(shí)現(xiàn):

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

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

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

  • 創(chuàng)建 .proto ?件時(shí),?件命名應(yīng)該使?全?寫(xiě)字?命名,多個(gè)字?之間? _ 連接。 例如:lower_snake_case.proto
  • 書(shū)寫(xiě) .proto ?件代碼時(shí),應(yīng)使? 2 個(gè)空格的縮進(jìn)。

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

3.2 添加注釋

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

3.3 具體編寫(xiě)

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

syntax = "proto3";

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

package contacts;

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

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

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

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

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

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

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

  樣例:

// 聲明語(yǔ)法版本
syntax = "proto3";
// 聲明代碼的命名空間
package contacts;
//結(jié)構(gòu)化對(duì)象的描述
message PeopleInfo{
    // 各個(gè)字段描述:   字段類型  字段名 = 字段唯一編號(hào)
    string name = 1;
    int32 age = 2;
}

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

3.4 編譯 contacts.proto 文件

  編譯命令?格式為:

protoc [--proto_path=IMPORT_PATH] --cpp_out=DST_DIR path/to/file.proto
protoc             是 Protocol Buffer 提供的命令?編譯?具。
--proto_path       指定被編譯的.proto?件所在?錄,可多次指定??珊?jiǎn)寫(xiě)成 -I IMPORT_PATH 。如不指
                   定該參數(shù),則在當(dāng)前?錄進(jìn)?搜索。當(dāng)某個(gè).proto ?件 import 其他.proto ?件時(shí),
                   或需要編譯的 .proto ?件不在當(dāng)前?錄下,這時(shí)就要?-I來(lái)指定搜索?錄。
--cpp_out=         指編譯后的?件為 C++ ?件。
OUT_DIR            編譯后?成?件的?標(biāo)路徑。
path/to/file.proto 要編譯的.proto?件

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

protoc --cpp_out=. contacts.proto

  編譯 contacts.proto ?件后,會(huì)?成所選擇語(yǔ)?的代碼,我們選擇的是C++,所以編譯后?成了兩個(gè)文件: contacts.pb.h contacts.pb.cc 。
  對(duì)于編譯?成的 C++ 代碼,包含了以下內(nèi)容 :

  • 對(duì)于每個(gè) message ,都會(huì)?成?個(gè)對(duì)應(yīng)的消息類
  • 在消息類中,編譯器為每個(gè)字段提供了獲取和設(shè)置?法,以及?下其他能夠操作字段的方法
  • 編輯器會(huì)針對(duì)于每個(gè) .proto ?件?成 .h 和 .cc ?件,分別?來(lái)存放類的聲明與類的實(shí)現(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);
};

  上述的例?中:

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

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

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

  注意:

  • 序列化的結(jié)果為?進(jìn)制字節(jié)序列,???本格式。
  • 以上三種序列化的?法沒(méi)有本質(zhì)上的區(qū)別,只是序列化后輸出的格式不同,可以供不同的應(yīng)?場(chǎng)景使?。
  • 序列化的 API 函數(shù)均為const成員函數(shù),因?yàn)樾蛄谢粫?huì)改變類對(duì)象的內(nèi)容, ?是將序列化的結(jié)果保存到函數(shù)?參指定的地址中

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

  • 對(duì)?個(gè)聯(lián)系?的信息使? PB 進(jìn)?序列化,并將序列化結(jié)果打印出來(lái)。
  • 對(duì)序列化后的內(nèi)容使? PB 進(jìn)?反序列,解析出聯(lián)系?信息并打印出來(lái)。
#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;
}

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

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

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

    過(guò)大的日志文件維護(hù)起來(lái)存在諸多問(wèn)題,所以最好是能夠按日或按大小切分日志文件,下面小編給大家?guī)?lái)了Spring boot按日切分spring boot的nohup.out日志文件的方法,一起看看吧
    2018-08-08
  • Java的字符串中對(duì)子字符串的查找方法總結(jié)

    Java的字符串中對(duì)子字符串的查找方法總結(jié)

    這篇文章主要介紹了Java的字符串中對(duì)子字符串的查找方法總結(jié),是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Java 異常的知識(shí)整理

    Java 異常的知識(shí)整理

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

    XFire構(gòu)建web service客戶端的五種方式

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

    Java中json與javaBean幾種互轉(zhuǎn)的講解

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

    SpringBoot整合easy-es的詳細(xì)過(guò)程

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

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

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

最新評(píng)論