我想找到一种方法将二进制protobuf消息转换为包含数据的人类可读描述,而不使用.proto文件。
背景是我有一条.proto消息说它被Android上的解析器拒绝了,但是为什么并不完全清楚。我可以手工完成这个消息,但这很乏味。
我尝试protoc --decode_raw
,但它只是给出错误“无法解析输入。”。我谷歌希望/期望有人会做一个很好的网络工具,可能会做到这一点,但没有找到任何明显的。
我只是希望获得一些输出:
field 1: varint: 128
field 4: string: "foo"
任何正确方向的指针都是最受欢迎的!
答案 0 :(得分:28)
对于后人: Google的协议缓冲区tools可以解码原始缓冲区。
只需将未知缓冲区发送给它并传递--decode_raw
标志
$ cat has_no_proto.buff | protoc --decode_raw
2 {
2: "Error retrieving information from server. [RH-02]"
}
所以这是一条消息,其中字段2设置为嵌入消息,而消息又具有 它的第二个字段设置为一个字符串,告诉我我生气了Google Play。
类型信息不明确(看起来它会尝试将所有二进制数据显示为字符串 - 但是满足了对varint / string / submessage区别的要求。)
答案 1 :(得分:8)
正如Michel de Ruiter's answer中所述,您的protobuf消息可能有length-prefix。假设确实如此,这个答案应该会有所帮助。
(注意:对于下面的大多数命令,我假设您的protobuf消息存储在名为input
的文件中。)
protoc --decode_raw
+ dd
:如果它只是一条消息,那么您确实可以利用protoc --decode_raw
,但您需要先删除长度前缀标头。假设标题长度为4个字节,您可以使用dd
从input
中删除标题,然后将输出反馈到protoc
。
dd bs=1 skip=4 if=input 2>/dev/null | protoc --decode_raw
单个邮件的protoc-decode-lenprefix --decode_raw
:我还写了一个script来自动处理标题剥离:
protoc-decode-lenprefix --decode_raw < input
此脚本只是protoc --decode_raw
之上的包装器,但处理解析长度前缀标头然后调用protoc
。
现在,在这种情况下,这个脚本并不是非常有用,因为我们可以使用上面的dd
技巧来删除标题。但是,假设我们有一个数据流(例如,文件或TCP流),其中包含多个以长度前缀标题框起的消息....
protoc-decode-lenprefix --decode_raw
表示消息流:而不是输入文件中的单个protobuf消息,假设input
包含多个protobuf消息,这些消息由长度前缀标头构成。在这种情况下,只是使用dd
技巧是不可能的,因为您需要实际读取length-prefix标头的内容以确定流中后续消息的时长,因此,下一个标题+消息前面有多少字节。因此,您不必担心所有这些,只需再次使用protoc-decode-lenprefix
:
protoc-decode-lenprefix --decode_raw < input
protoc-decode-lenprefix --decode ... foo.proto
用于消息流此脚本还可用于完全解码长度前缀的消息(而不仅仅是&#34;原始解码&#34;它们)。它假定您可以访问定义protobuf消息的.proto
文件,就像包装的protoc
命令一样。调用语法与protoc --decode
相同。例如,将dd
技巧与protoc --decode
一起使用,输入为Mesos task.info文件,语法如下所示:
dd bs=1 skip=4 if=task.info 2>/dev/null | \
protoc --decode mesos.internal.Task \
-I MESOS_CODE/src -I MESOS_CODE/include \
MESOS_CODE/src/messages/messages.proto
使用protoc-decode-lenprefix
cat task.info | \
protoc-decode-lenprefix --decode mesos.internal.Task \
-I MESOS_CODE/src -I MESOS_CODE/include \
MESOS_CODE/src/messages/messages.proto
答案 2 :(得分:7)
如果您碰巧有一个包含(多个?)长度前缀 protobuf消息的二进制文件,protoc ‒‒decode_raw < file
由于长度前缀而无法解析它。一个简单的方法是将文件拆分为连续的消息,然后将每个消息转换为protoc
。
我的看法:
var fs = File.OpenRead(filename));
var buffer = new byte[4096];
int size;
for (int part = 1; Serializer.TryReadLengthPrefix(fs, PrefixStyle.Base128, out size); part++) {
long startPosition = fs.Position;
using (var writer = File.OpenWrite(string.Format("{0}[{1}].pb", filename, part))) {
for (int bytesToRead = size; bytesToRead > 0; ) {
int bytesRead = fs.Read(buffer, 0, Math.Min(bytesToRead, buffer.Length));
bytesToRead -= bytesRead;
if (bytesRead <= 0) // End of file.
break;
writer.Write(buffer, 0, bytesRead);
}
}
}
答案 3 :(得分:6)
您可以尝试强制通过wireshark插件,或者您可以借用某些实现的“读者”部分(例如,我知道如何在C#中执行此操作,但我怀疑这就是您的意思)。
但是,要小心 - 协议缓冲区中的字符串并不真正意味着“字符串” - 它可能是:
答案 4 :(得分:1)
也许试试https://pb-decode.online。我是作者,欢迎提出建议:)