简体   繁体   English

C ++ protobuf:如何通过“SerializeToOstream()”将多个消息写入文件

[英]C++ protobuf: how to write multiple messages into file by “SerializeToOstream()”

I found when I use SerializeToOstream(), only the last message was written to file, and previous ones are all overwritten by later calls. 我发现当我使用SerializeToOstream()时,只有最后一条消息被写入文件,之前的消息都被以后的调用覆盖。 Like this: 像这样:

I've my hello.proto: 我是你的hello.proto:

message hello
{
    required int32 f1=1;
    required int32 f2=2;
    optional int32 f3=3;
}

Then I had it compiled and used in one cpp file: 然后我编译并在一个cpp文件中使用它:

#include "hello.pb.h"
#include<fstream>
#include<iostream>
using namespace std;
int main()
{
    fstream fo("./hello.data",ios::binary|ios::out);
    hello p1,p2,p3;
    p1.set_f1(1);
    p1.set_f2(2);
    p2.set_f1(3);
    p2.set_f2(4);
    p3.set_f1(5);
    p3.set_f2(6);
    p1.SerializeToOstream(&fo);
    p2.SerializeToOstream(&fo);
    p3.SerializeToOstream(&fo);
    fo.close();

    fstream fi("./hello.data",ios::binary|ios::in);
    hello pi;
    pi.ParseFromIstream(&fi);
    cout<<pi.f1()<<pi.f2()<<endl;
    return 0;
}

Well I found only "p3" was writen into this "hello.data", the p1 and p2 were overwritten in some way? 好吧,我发现只有“p3”被写入这个“hello.data”,p1和p2被覆盖了某种方式?

Why protobuf only write the last message? 为什么protobuf只写最后一条消息? We usually use protobuf to communicate multiple messages, right? 我们通常使用protobuf来传递多条消息,对吧? So how to write multiple messages into one file? 那么如何将多条消息写入一个文件? How to correct my program? 如何纠正我的程序?

The problem here is that protocol buffers are not self-delimiting; 这里的问题是协议缓冲区不是自定界限的; to parse a message you must know in advance how many bytes to read. 要解析一条消息,您必须事先知道要读取多少字节。 Because of the way the wire format works, you can concatenate two (or more) serialized protocol buffers and still have a valid message; 由于有线格式的工作方式,您可以连接两个(或更多)序列化协议缓冲区,但仍然有一个有效的消息; for any given singular field, later values take precedence over earlier ones. 对于任何给定的奇异域,后面的值优先于先前的值。 So what is happening is that ParseFromIstream is reading all three serialized messages as if they were one message, and the last message is effectively taking precedence over the two previous ones. 所以发生的事情是ParseFromIstream正在读取所有三个序列化消息,就像它们是一条消息一样,并且最后一条消息实际上优先于前两条消息。

To fix this, you have to include some kind of message-length prefix for each message. 要解决此问题,您必须为每条消息包含某种消息长度前缀。 Typically this is done by prefixing each message with a varint storing its length. 通常,这是通过为每个消息添加一个存储其长度的varint来完成的。 This code from Kenton Varda is a good example of exactly how to do this in C++. 这个来自Kenton Varda的代码是一个很好的例子,说明如何在C ++中做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM