是否可以使用 google.protobuffer 序列化数据而无需为每个数据字段的长度添加前缀?

Is it possible to use google.protobuffer to serialize data without prefixing the length of each data field?

默认情况下,除非我做错了什么,否则protobuf会在所有数据字段前加上后面数据的长度作为前缀。例如,如果我这样做:

class Program
{
    static void Main(string[] args)
    {
        MessagePayload msg = new MessagePayload()
        {
            Message = "hello"
        };

        var bytes = new byte[8];

        var output = new CodedOutputStream(bytes);

        output.WriteMessage(msg);

        Console.WriteLine(CryptoBytes.ToHexStringLower(bytes));

        Console.ReadLine();
    }
}

它打印出来:

07120568656c6c6f

但我想要的是:

0568656c6c6f

有没有办法让 protobuf 以某种方式执行此操作,而无需手动删除长度字段?

没有。如此处的编码所述 https://developers.google.com/protocol-buffers/docs/encoding 字符串必须全部以其大小作为前缀。 "A wire type of 2 (length-delimited) means that the value is a varint encoded length followed by the specified number of bytes of data. "

那里唯一可移动的字节是 07 - 这不是常规 protobuf 规范的一部分,并且该消息的 原始 protobuf 输出 是只是 120568656c6c6f。前导 07 是一个不相关的长度前缀,可能是 CodedOutputStream 的一部分,但 而不是 常规 protobuf 输出的一部分。您可能可以通过 不使用 CodedOutputStream 来避免这种情况,而只是使用可能在 msg.

上的其他可用方法

这里的12表示"field number: 2, type: length-delimited"。这告诉我 Message 很可能不是 MessagePayload 上定义的唯一字段,所以不:你不能删除它。即使它 MessagePayload 上的唯一字段:protobuf 规范并不关心:每个字段都存在 得到一个字段 header.

老实说,如果你只想发送一个字符串,那么:不要使用 protobuf - 只需使用 UTF-8 编码字符串,在前面加上length-prefix 以您选择的任何方式(protobuf 使用 "varint"),您就完成了。但是,如果您想发送更复杂的结构化数据,则需要 一些开销 才能做到这一点。这就是 12 的意思。

备案:protobuf 中定义了 6 个 "wire types",其中只有一个(wire type 2)涉及长度前缀。许多字段 涉及长度前缀。在您的示例中,实际 protobuf 数据 中唯一的长度前缀 05,这是您说 希望保留的字节之一 .