3

给定一个已编码的协议缓冲区Streambyte[]不知道对象类型本身,我们如何打印消息的骨架?该用例用于调试基于 protobuf 的 IO,用于根本原因分析。

如果有现有的工具可以从二进制文件中解析原始协议缓冲区字节流——那就太好了!另一种方法是使用 ProtoBuf.NET 类ProtoReader()来继续运行,直到我们遇到错误,但 ProtoReader() 的用法尚不清楚。我从下面开始,但找不到关于如何使用ProtoReader该类来实际执行它的好的文档。该项目的源代码也不是很容易理解......所以希望得到一些提示/帮助

using (var fs = File.OpenRead(filePath))
{
    using (var pr = new ProtoReader(fs, TypeModel.Create(), null))
    {
        // Use ProtoReader to march through the bytes
        // Printing field number, type, size and payload values/bytes
    }
}
4

1 回答 1

3

首先,请注意,谷歌“protoc”命令行工具具有尝试反汇编没有架构信息的原始消息的选项。使用 protobuf-net,您可以执行以下操作 - 但我需要强调的是,如果没有 schema,格式是不明确的:数据类型/格式比“有线类型”(实际编码格式)更多。在这里,我只是展示了可能的解释,但还有其他方法可以解析相同的数据。

static void WriteTree(ProtoReader reader)
{
    while (reader.ReadFieldHeader() > 0)
    {
        Console.WriteLine(reader.FieldNumber);
        Console.WriteLine(reader.WireType);
        switch (reader.WireType)
        {
            case WireType.Variant:
                // warning: this appear to be wrong if the 
                // value was written signed ("zigzag") - to
                // read zigzag, add: pr.Hint(WireType.SignedVariant);
                Console.WriteLine(reader.ReadInt64());
                break;
            case WireType.String:
                // note: "string" here just means "some bytes"; could
                // be UTF-8, could be a BLOB, could be a "packed array",
                // or could be sub-object(s); showing UTF-8 for simplicity
                Console.WriteLine(reader.ReadString());
                break;
            case WireType.Fixed32:
                // could be an integer, but probably floating point
                Console.WriteLine(reader.ReadSingle());
                break;
            case WireType.Fixed64:
                // could be an integer, but probably floating point
                Console.WriteLine(reader.ReadDouble());
                break;
            case WireType.StartGroup:
                // one of 2 sub-object formats
                var tok = ProtoReader.StartSubItem(reader);
                WriteTree(reader);
                ProtoReader.EndSubItem(tok, reader);
                break;
            default:
                reader.SkipField();
                break;
        }
    }
}

或在 v3 中:https ://stackoverflow.com/a/64621670/23354

于 2013-10-29T08:04:02.900 回答