例如,如果我这样定义一张照片:
$cat 30.proto
message hello
{
required int32 f1=1;
required int32 f2=2;
optional int32 f3=3;
}
如果 protobuf 可以处理这样的事情,我会加倍:
我声明了 3 个对象,每个对象都没有
f3
字段。写入输出
那么,在读者端,读者如何知道这6个值应该属于3个对象(每个2个字段),还是属于2个对象(每个3个字段)?
换句话说,编码字节中的“require”/“optional”是如何体现的?如果没有体现在字节流中,那么protobuf是如何确定一个新偏移量的开始呢?我们知道 protobuf 没有“分隔符”位。
我对此进行了简单的快速测试:
$cat 30.cpp
#include "30.pb.h"
#include<fstream>
using namespace std;
int main()
{
fstream f("./log30.data",ios::binary|ios::out);
hello p1,p2,p3,p4,p5;
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(&f);
p2.SerializeToOstream(&f);
p3.SerializeToOstream(&f);
p4.set_f1(7);
p4.set_f2(8);
p4.set_f3(9);
p5.set_f1(0xa);
p5.set_f2(0xb);
p5.set_f3(0xc);
p4.SerializeToOstream(&f);
p5.SerializeToOstream(&f);
return 0;
}
$g++ 30.cpp 30.pb.cc -lprotobuf && ./a.out && xxd log30.data
00000000: 0801 1002 0803 1004 0805 1006 0807 1008 ................
00000010: 1809 080a 100b 180c ........
我只是猜测字节流是否总是以最小的标记号开始,并随着它转储字节流而增加:当遇到较小的标记号时,它认为这是一个新对象的开始。只是我的粗略猜测。
需要你的解释!
最佳答案
(3) Then, in reader side, how does reader know that these 6 values should belong to 3 objects(each 2 fields), or belong to 2 objects(each 3 fields)?
In another word, how does the "require"/"optional" reflected inside encoded bytes? If not reflected in the byte stream, then how does protobuf determine the start of a new offset? We know protobuf don't have "delimiter" bits.
Protobuf 没有。在将消息提供给 protobuf 之前,由您(程序员)来拆分消息。
例如,运行这个程序:
#include "30.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
fstream f("./log30.data",ios::binary|ios::out);
hello p1,p2,p3,p4,p5;
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(&f);
p2.SerializeToOstream(&f);
p3.SerializeToOstream(&f);
p4.set_f1(7);
p4.set_f2(8);
p4.set_f3(9);
p5.set_f1(0xa);
p5.set_f2(0xb);
p5.set_f3(0xc);
p4.SerializeToOstream(&f);
p5.SerializeToOstream(&f);
f.close();
f.open("./log30.data", ios::binary|ios::in);
hello hin;
hin.ParseFromIstream(&f);
cout << "f1: " << hin.f1() << ", f2: " << hin.f2() << ", f3: " << hin.f3() << "\n";
return 0;
}
您应该只会看到上次序列化的 hello
对象的值,因为 protobuf 会读取整个 流并用新值覆盖旧值。
关于linux - protobuf如何判断一个值是属于可选字段,还是属于另一个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41614027/