0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

protobuf怎么發(fā)現(xiàn)的?

科技綠洲 ? 來(lái)源:了不起 ? 作者:了不起 ? 2023-09-25 11:26 ? 次閱讀

最近我們?cè)陧?xiàng)目中,通過(guò)使用 protobuf 格式作為存儲(chǔ)數(shù)據(jù)的一個(gè)載體。一個(gè)不小心就給自己埋了個(gè)大坑,還是過(guò)了好久才發(fā)現(xiàn)。

protobuf 簡(jiǎn)介

protobuf 全名叫 Protocal buffers. 它是由 Google 研發(fā)的,一種可跨語(yǔ)言、可跨平臺(tái)、可擴(kuò)展的序列化數(shù)據(jù)的機(jī)制。類似于 XML ,但是它更小、更快、更簡(jiǎn)單。你只需要定義一次你希望的數(shù)據(jù)如何被結(jié)構(gòu)化,然后你可以使用它的生成工具,生成包含一些序列化和反序列化等操作的源代碼??梢暂p松地從各種數(shù)據(jù)流和使用各種編程語(yǔ)言寫入和讀取結(jié)構(gòu)化的數(shù)據(jù)。

proto2版本支持在JavaPython、Objective-C和C++中生成代碼。使用新的proto3語(yǔ)言版本,你還可以使用Kotlin、Dart、Go、Ruby、PHP和C#,還有更多的語(yǔ)言。

怎么發(fā)現(xiàn)的?

在我們的新項(xiàng)目中,我們通過(guò)使用 protobuf 格式來(lái)存儲(chǔ)項(xiàng)目運(yùn)行的數(shù)據(jù)。這樣我們?cè)谡{(diào)試過(guò)程中,可能根據(jù)現(xiàn)場(chǎng)錄制的數(shù)據(jù)進(jìn)行本地的調(diào)試。

message ImageData {
// ms
int64 timestamp = 1;
int32 id = 2;
Data mat = 3;
}

message PointCloud {
// ms
int64 timestamp = 1;
int32 id = 2;
PointData pointcloud = 3;
}

message State {
  // ms
  int64 timestamp = 1;
  string direction = 2;
}

message Sensor {
repeated PointCloud point_data = 1;
repeated ImageData image_data = 2;
repeated State vehicle_data = 3;
}

我們定義了這樣一組數(shù)據(jù), 然后存儲(chǔ)的時(shí)候,因?yàn)镾ensor 這3個(gè)數(shù)據(jù)源的幀率不一樣,因此存儲(chǔ)的時(shí)候,單個(gè) Sensor 中其實(shí)只包含了一組數(shù)據(jù),另外兩個(gè)類型的數(shù)據(jù)并沒(méi)有包含進(jìn)去。

當(dāng)我們只錄制單個(gè) pack 的時(shí)候,我們并沒(méi)有遇到問(wèn)題。直到我們覺得單個(gè)包,不能長(zhǎng)時(shí)間錄制,我們需要找一種解決方法來(lái)分割包 。

當(dāng)時(shí)覺得這個(gè)一定是很簡(jiǎn)單的,我們就設(shè)定了一個(gè)包達(dá)到 500M 的時(shí)候,我們就讓后面的數(shù)據(jù)存到新的包中。很順利的寫完,然后放到現(xiàn)場(chǎng)進(jìn)行數(shù)據(jù)錄制。錄制一段時(shí)間之后,我們把包拿回來(lái)進(jìn)行模擬測(cè)試我們的新程序。發(fā)現(xiàn)有些包的數(shù)據(jù)解析出來(lái)是有問(wèn)題的。程序運(yùn)行到一半會(huì)卡在那里不動(dòng)。經(jīng)過(guò)多次測(cè)試,發(fā)現(xiàn)是部分包有這個(gè)問(wèn)題。

我們一開始懷疑的是,判斷文件大小的方式不對(duì),影響到了分包。因?yàn)榕袛辔募笮〉臅r(shí)候,會(huì)去打開文件。但是經(jīng)過(guò)好幾種其他的不打開文件的方式判斷,從而進(jìn)行分割。還是遇到了部分錄制的包有問(wèn)題。

這時(shí)我才懷疑到 protobuf 對(duì)存儲(chǔ)數(shù)據(jù)會(huì)有一些特殊的要求。后來(lái)看了一些文章,了解到 protobuf 存儲(chǔ)多組數(shù)據(jù)到一個(gè)文件需要有標(biāo)志符。要不然后面從文件解析回來(lái)的時(shí)候,protobuf 因?yàn)椴恢绬蝹€(gè)數(shù)據(jù)的停止符在哪里,導(dǎo)致數(shù)據(jù)解析出錯(cuò)。

到這里,這個(gè)坑出現(xiàn)了。我們存儲(chǔ)了一系列的數(shù)據(jù)到單個(gè)包中,沒(méi)有做任何分隔符的操作。protobuf在解析的時(shí)候,把文件中所有的內(nèi)容都解析成了單個(gè)Sensor。Sensor 中包含里所有數(shù)據(jù), protobuf 主動(dòng)合并了所有存儲(chǔ)的數(shù)據(jù)。

在這時(shí),我才發(fā)現(xiàn)以前單包錄制的時(shí)候,數(shù)據(jù)都是對(duì)的,那真的是我運(yùn)氣好。protobuf恰好解析成功了。

怎么解決呢?

既然知道 protobuf 會(huì)這么操作,那我們就只要知道 protobuf 怎么分割就行了。這個(gè)方法還真不好找,因?yàn)橄裎覀冞@樣使用的人太少了。中文搜索完全搜不到這一塊的內(nèi)容,可能大家都不會(huì)使用protobuf來(lái)存儲(chǔ)數(shù)據(jù)吧,大家使用的方式應(yīng)該都是多個(gè)服務(wù)中進(jìn)行交互的場(chǎng)景吧。

最終通過(guò)stackoverflow上的一些回答找到了答案,從回答中得知,這個(gè)解決辦法在 protobuf 3.3 的時(shí)候,才正式被合并進(jìn)去??雌饋?lái)這個(gè)功能真的很少用啊。

bool SerializeDelimitedToOstream(const MessageLite& message,
                                                 std::ostream* output);
bool ParseDelimitedFromZeroCopyStream(
    MessageLite* message, io::ZeroCopyInputStream* input, bool* clean_eof);

通過(guò)這一對(duì)方法,可以對(duì)文件進(jìn)行按照數(shù)據(jù)流一個(gè)一個(gè)的存儲(chǔ)讀取。再也不用擔(dān)心數(shù)據(jù)被合并讀取。

當(dāng)然通過(guò)這種方式存儲(chǔ)的數(shù)據(jù),不能被原來(lái)的解析方式所解析,存儲(chǔ)的而進(jìn)行格式完全變了。這種方式會(huì)先存儲(chǔ)二進(jìn)制數(shù)據(jù)的大小,再存儲(chǔ)二進(jìn)制數(shù)據(jù)。

結(jié)束語(yǔ)

經(jīng)過(guò)一番折騰,終于搞定了這個(gè)分割的坑。使用場(chǎng)景可能比較小眾,導(dǎo)致了很多資料根本找不到??孔约嚎丛创a才發(fā)現(xiàn)這些問(wèn)題。C++ 的源碼真不好讀,有很多的模板方法、模板類容易錯(cuò)過(guò)一些細(xì)節(jié)。最后還是看的C#的代碼,才完全確認(rèn)的。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編程語(yǔ)言
    +關(guān)注

    關(guān)注

    10

    文章

    1945

    瀏覽量

    34746
  • 源代碼
    +關(guān)注

    關(guān)注

    96

    文章

    2945

    瀏覽量

    66752
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4788

    瀏覽量

    68628
  • 存儲(chǔ)數(shù)據(jù)

    關(guān)注

    0

    文章

    88

    瀏覽量

    14103
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【LeMaker Guitar試用體驗(yàn)】8.Lemuntu系統(tǒng)中編譯protobuf源代碼和簡(jiǎn)單示例

    本帖最后由 xble 于 2016-2-17 11:42 編輯 protobuf是什么東東?http://blog.csdn.net/menuconfig/article/details
    發(fā)表于 02-17 11:42

    請(qǐng)教關(guān)于z-stack linux gateway 中更新protobuf-c的問(wèn)題

    我下載了z-stack linux gateway 然后嘗試編譯到PC機(jī)去執(zhí)行,按照流程,我下載了 protobuf2.6.1版本。protobuf-c1.2.1版本,并且在ubuntu上也安裝
    發(fā)表于 08-09 08:11

    請(qǐng)問(wèn)liunx gate編輯出錯(cuò)怎么處理?

    目標(biāo)平臺(tái)MTK-76281.根據(jù)手冊(cè),需要編譯protobuf下載源碼后,./configure --build=i386-pc-linux --host=mipsel-openwrt-linux
    發(fā)表于 08-18 07:12

    Go Protobuf資源的可讀化 ,看完你就懂了

    Go Protobuf資源的可讀化 ,看完你就懂了
    發(fā)表于 06-15 09:08

    利用protobuf通信原理

    一、利用protobuf通信原理最近項(xiàng)目中需要用到stm32與H6(移植了linux)進(jìn)行數(shù)據(jù)交互,H6端是用C++編寫的串口底層驅(qū)動(dòng),與stm32的串口連接并通信。-串口間的通信協(xié)議定為采用
    發(fā)表于 08-20 07:25

    什么是protobuf?怎么使用?

    什么是protobuf-c 之前的文章:《Protobuf:一種更小、更快、更高效的協(xié)議》詳細(xì)介紹了protobufprotobuf-c。這里再簡(jiǎn)單提一下:Protocol Buff
    發(fā)表于 12-16 06:03

    如何去解決S5P6818交叉編譯protobuf報(bào)錯(cuò)的問(wèn)題

    /arm-cortex_a9-linux-gnueabi-g++ supports C++11 features with -h std=c++0x... noS5P6818交叉編譯protobuf報(bào)錯(cuò)編譯器不支持C++11怎么辦開發(fā)板是OK6818-C,也可以使用嗎
    發(fā)表于 01-06 06:39

    protobuf在STM32平臺(tái)的移植使用方法

    說(shuō)在前面的話 這是一篇2020年欠下的文章,一直擱置著,現(xiàn)在還上。之前分享了兩篇關(guān)于Protobuf的筆記:Proto...
    發(fā)表于 01-11 06:26

    protobuf是什么?protobuf有什么作用支持什么數(shù)據(jù)類型?

    protobuf是google旗下的一款平臺(tái)無(wú)關(guān),語(yǔ)言無(wú)關(guān),可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式。所以很適合用做數(shù)據(jù)存儲(chǔ)和作為不同應(yīng)用,不同語(yǔ)言之間相互通信的數(shù)據(jù)交換格式,只要實(shí)現(xiàn)相同的協(xié)議格式即同一
    發(fā)表于 09-27 16:29 ?3次下載

    深入剖析ProtoBuf原理與工程實(shí)踐

    ProtoBuf 作為一種跨平臺(tái)、語(yǔ)言無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)的方法,已廣泛應(yīng)用于網(wǎng)絡(luò)數(shù)據(jù)交換及存儲(chǔ)。隨著互聯(lián)網(wǎng)的發(fā)展,系統(tǒng)的異構(gòu)性會(huì)愈發(fā)突出,跨語(yǔ)言的需求會(huì)愈加明顯,同時(shí) gRPC 也大有取代
    的頭像 發(fā)表于 11-16 09:15 ?1583次閱讀
    深入剖析<b class='flag-5'>ProtoBuf</b>原理與工程實(shí)踐

    Protocol Buffer在MCU上的實(shí)現(xiàn)--C語(yǔ)言

    一 什么是Protocol BufferProtocol Buffer是一種支持多平臺(tái)、多語(yǔ)言、可擴(kuò)展的的數(shù)據(jù)序列化機(jī)制,相較于XML來(lái)說(shuō),protobuf更小更快更簡(jiǎn)單,支持自定義的數(shù)據(jù)結(jié)構(gòu),用
    發(fā)表于 11-20 13:21 ?10次下載
    Protocol Buffer在MCU上的實(shí)現(xiàn)--C語(yǔ)言

    Intellij IDEA插件idea-plugin-protobuf

    ./oschina_soft/idea-plugin-protobuf.zip
    發(fā)表于 05-18 11:09 ?2次下載
    Intellij IDEA插件idea-plugin-<b class='flag-5'>protobuf</b>

    使用Protobuf實(shí)現(xiàn)客戶端與服務(wù)器之間的通信協(xié)議層

    本系列是關(guān)于用Rust構(gòu)建一個(gè)KV Server的系列文章,內(nèi)容包括用tokio做底層異步網(wǎng)絡(luò)通訊、使用toml文件做配置、protobuf做傳輸協(xié)議、內(nèi)存/RockDB做數(shù)據(jù)存儲(chǔ)、事件通知、優(yōu)雅關(guān)機(jī)、并發(fā)連接限制及測(cè)量監(jiān)控等。
    的頭像 發(fā)表于 09-14 09:26 ?2520次閱讀

    結(jié)構(gòu)化數(shù)據(jù):ProtoBuf試用與JSON的比較

    XML、JSON 也可以用來(lái)存儲(chǔ)此類結(jié)構(gòu)化數(shù)據(jù),但是使用ProtoBuf表示的數(shù)據(jù)能更加高效,并且將數(shù)據(jù)壓縮得更小。
    發(fā)表于 03-08 15:43 ?1863次閱讀

    protobuf的編碼和存儲(chǔ)方式

    一、protobuf簡(jiǎn)介: 1.1 protobuf的定義: protobuf是用來(lái)干嘛的? protobuf是一種用于 對(duì)結(jié)構(gòu)數(shù)據(jù)進(jìn)行序列化的工具,從而實(shí)現(xiàn) 數(shù)據(jù)存儲(chǔ)和交換。 (主要
    的頭像 發(fā)表于 11-09 09:27 ?1350次閱讀
    <b class='flag-5'>protobuf</b>的編碼和存儲(chǔ)方式