【发布时间】:2010-07-12 11:35:57
【问题描述】:
我想比较Google protocol buffers 的两个消息或(两个子参数)。 我没有找到实现它的 API。
有什么想法吗?
【问题讨论】:
-
您能具体说明您要比较的内容:消息结构、消息的字段值还是两者兼而有之?
标签: c++ protocol-buffers
我想比较Google protocol buffers 的两个消息或(两个子参数)。 我没有找到实现它的 API。
有什么想法吗?
【问题讨论】:
标签: c++ protocol-buffers
您可以为此使用 google::protobuf::util::MessageDifferencer 类。我认为它仅在v3.0.2之后可用:
在 google/protobuf/util 中引入了新的实用函数/类 目录:
- MessageDifferencer:比较两个原始消息并报告它们的差异。
#include <google/protobuf/util/message_differencer.h>
MessageDifferencer::Equals(msg1, msg2);
【讨论】:
MessageDifferencer::Equivalent 而不是Equals
MessageDifferencer::Equals 要求参数为Message 而不是MessageLite(其中Message导出)。 Equals 需要 GetDescriptor(),这是一个仅在 Message 中实现的功能。因此,在这种情况下,您必须了解其他答案中提到的一种序列化方法,并充分了解其局限性。
您可以依赖这样一个事实,即所有 protobuf 消息都继承自 google::protobuf::MesageLite 类型,这反过来又具有比较任何两个 protobuf 消息所需的一切,无论它们是否属于相同的派生类型:
bool operator==(const google::protobuf::MessageLite& msg_a,
const google::protobuf::MessageLite& msg_b) {
return (msg_a.GetTypeName() == msg_b.GetTypeName()) &&
(msg_a.SerializeAsString() == msg_b.SerializeAsString());
}
编辑
正如下面的 cmets 所指出的,尤其是对于 map 字段,这个答案是不正确的。 map 元素具有不确定的顺序。如果您的消息中可能存在map 字段,请使用MessageDifferencer。
【讨论】:
MessageDifferencer::Equals(msg1, msg2);快
map 字段尤其适用。如果您的 protobuf 消息可能包含 map 字段,则 SerializeAsString() 将不确定地失败。
除了使用message.DebugString,你也可以这样做
std::string strMsg;
message.SerializeToString(&strMsg);
同时使用两个消息,然后比较两个(二进制)字符串。我没有测试性能,但我认为它比比较 .DebugString() 返回的人类可读消息字符串要快。 +您可以使用 protobuf-lite 库来做到这一点(而对于 message.DebugString,您需要完整版本)。
【讨论】:
好吧,协议缓冲区只是某些对象类型的序列化格式。为什么不使用协议缓冲区来重构原始对象,然后允许这些对象使用您在类中内置的任何比较逻辑来比较它们自己?
【讨论】:
这可能不是理想的解决方案,但我认为可以通过以下方式完成:
messageA.DebugString() == messageB.DebugString();
除此之外,我认为唯一的解决方案是创建自己的Message 子类并实现bool operator==(const Message&)。
【讨论】:
可以比较描述符的指针(超快):
if (mMessages[i]->body()->GetDescriptor() == T::descriptor())
mMessages 它是一个带有标头和加密的网络消息池,它创建一个带有 protobuf 正文的数据包(google::protobuf::Message*)。
所以,为了获得正确类型的消息,我比较了描述符常量指针,这对于每种单一类型的消息都是相同的(不确定,但我没有遇到任何问题)。
这将是比较 protobuf 消息的最快方法,而不必使用字符串比较,顺便说一下,您可以从描述符中获取类型名称。 :-)
【讨论】: