我熟悉 protobuf 线路格式,其中设计者选择不包括线路上序列化消息的大小。
我也熟悉了从头开始应对的策略:
但是,我的看法略有不同(和问题)。
鉴于我无法控制的已经序列化的消息,我想一次加载它的每个字段。请注意,虽然序列化消息的大小未编码(请参阅前面的项目符号),但其每个字段的大小是编码的。此外,field id也被编码。请参阅此处。
所以从理论上讲,应该有可能有像下面的函数
ParseMsgField
这样的东西。如果给定一个先前序列化的 Root 对象(因此,它的字段确实被编码),则一次加载它的每个字段。
package my_proto;
message SubType0 {
uint32 Val = 1;
}
message SubType1 {
uint32 Val = 1;
}
message Root {
repeated SubType0 subtype = 1;
repeated SubType1 subtype = 2;
}
#include "my_proto.pb.h"
// how to implement this...?
int ParseMsgField(Descriptor* root_descriptor, Message* field_msg);
int main() {
auto* root_descriptor = my_proto::Root::descriptor();
google::protobuf::Message* field_msg;
while(true) {
int field_id = ParseMsgField(root_descriptor, field_msg);
if (field_id == -1) {
break;
}
// handle each field type, either dynamic_cast or test field_id + static_cast
}
我想知道如何实现
ParseMsgField
功能?我使用的输入参数是猜测我可能需要什么...
我想如果这是可能的,一个限制是 Root 的所有子类型都必须是消息类型才能工作?
要一次解析一个 Protobuf 消息字段,可以使用 Protobuf 库中的
ParseFromArray
或 ParseFromIstream
方法。这是一个简短的指南:
使用
ParseFromArray
:
MyMessage msg;
// Assuming 'data' is a byte array containing your Protobuf message
if (msg.ParseFromArray(data, size)) {
// Successfully parsed the entire message
// Access fields as needed
int field_value = msg.field_name();
} else {
// Handle parse error
}
使用
ParseFromIstream
:
MyMessage msg;
std::ifstream input_file("message.bin", std::ios::binary);
if (msg.ParseFromIstream(&input_file)) {
// Successfully parsed the message
// Access fields as needed
int field_value = msg.field_name();
} else {
// Handle parse error
}
要单独处理字段,您可以在解析后检查每个字段的存在和值。为了进行详细控制,如果 Protobuf 库支持此类操作,您可能需要迭代字段。
如果您需要更多具体细节或有任何其他问题,请告诉我! 访问:https://topfollow-apk.com/blog/