C++ protobuf:如何通过 "SerializeToOstream()" 将多条消息写入文件
C++ protobuf: how to write multiple messages into file by "SerializeToOstream()"
我发现当我使用SerializeToOstream()时,只有最后一条消息被写入文件,之前的消息都被后面的调用覆盖了。像这样:
我有我的 hello.proto:
message hello
{
required int32 f1=1;
required int32 f2=2;
optional int32 f3=3;
}
然后我把它编译并用在一个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;
}
嗯,我发现只有 "p3" 被写入此 "hello.data",p1 和 p2 以某种方式被覆盖了?
为什么protobuf只写最后一条消息?我们通常使用 protobuf 来传递多条消息,对吧?那么如何将多条消息写入一个文件呢?如何更正我的程序?
这里的问题是协议缓冲区不是自定界的;要解析一条消息,您必须事先知道要读取多少字节。由于有线格式的工作方式,您可以连接两个(或更多)序列化的协议缓冲区,并且仍然有一个有效的消息;对于任何给定的单数字段,后面的值优先于前面的值。所以发生的事情是 ParseFromIstream
正在读取所有三个序列化消息,就好像它们是一条消息一样,最后一条消息实际上优先于前两条消息。
要解决此问题,您必须为每条消息添加某种消息长度前缀。通常,这是通过在每条消息前加上 varint storing its length. This code 前缀来完成的,Kenton Varda 是一个很好的例子,说明了如何在 C++ 中做到这一点。
我发现当我使用SerializeToOstream()时,只有最后一条消息被写入文件,之前的消息都被后面的调用覆盖了。像这样:
我有我的 hello.proto:
message hello
{
required int32 f1=1;
required int32 f2=2;
optional int32 f3=3;
}
然后我把它编译并用在一个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;
}
嗯,我发现只有 "p3" 被写入此 "hello.data",p1 和 p2 以某种方式被覆盖了?
为什么protobuf只写最后一条消息?我们通常使用 protobuf 来传递多条消息,对吧?那么如何将多条消息写入一个文件呢?如何更正我的程序?
这里的问题是协议缓冲区不是自定界的;要解析一条消息,您必须事先知道要读取多少字节。由于有线格式的工作方式,您可以连接两个(或更多)序列化的协议缓冲区,并且仍然有一个有效的消息;对于任何给定的单数字段,后面的值优先于前面的值。所以发生的事情是 ParseFromIstream
正在读取所有三个序列化消息,就好像它们是一条消息一样,最后一条消息实际上优先于前两条消息。
要解决此问题,您必须为每条消息添加某种消息长度前缀。通常,这是通过在每条消息前加上 varint storing its length. This code 前缀来完成的,Kenton Varda 是一个很好的例子,说明了如何在 C++ 中做到这一点。