使用 Protobuf .net 反序列化单个结构字段

Posted

技术标签:

【中文标题】使用 Protobuf .net 反序列化单个结构字段【英文标题】:Deserialize single structure field using Protobuf .net 【发布时间】:2012-09-24 13:09:54 【问题描述】:

我有一个关于使用 Protobuf .Net 进行反序列化的问题。我正在尝试用它替换 XMLSerializer,但我找不到从文件中反序列化单个字段的方法。 如果文件被修改,我需要信息,这是保存结构中的字段之一。

这甚至可能吗?如果是,我可以寻求帮助吗?

问候

【问题讨论】:

在这种情况下,我认为如果您发布一些 XMLSerializer 代码作为使用 protobuf.net 回答的基础,这将有助于人们解决问题 【参考方案1】:

在大多数情况下,坦率地说,您可以反序列化整个事情 - 它会很快,等等。但是,如果您真的想要限制它,有几个选项。

最简单的方法是创建一个较小的模型,上面只包含您想要的信息。所以:如果您的原始模型上有 46 个字段,其中 5 个是集合等 - 但您只想要字段 12 中的 Version,那么:

[ProtoContract]
public class InsertNameHere 
    [ProtoMember(12)]
    public int Version get;set;

现在反序列化 那个

var obj = Serializer.Deserialize<InsertNameHere>(source);
int version = obj.Version;

这会起作用,因为 protobuf-net 是基于合约的;它不必是完全相同的类型,只要它看起来足够接近即可。不过,更高级的方法是使用ProtoReader

int version = 0;
using (var reader = new ProtoReader(source, RuntimeTypeModel.Default, null))

    int field;
    bool keepReading = true;
    while ((field = reader.ReadFieldHeader()) > 0 && keepReading)
       
        switch (field)
        
            case 12:
                version = reader.ReadInt32();
                // STOP LOOPING (leaves the stream partly-read)
                keepReading = false;
                break; 
            default:
                reader.SkipField();
                break;
        
    

您可能想要使用上述内容的原因是它可以提前停止查找 - 即,一旦我们找到我们的字段 12,我们就可以在不处理文件的其余部分的情况下杀死阅读器.通常情况下,如果我们知道数据很大并且我们不需要太多数据,我只会使用第二种方法。

技术上 protobuf 是一种可附加格式有一个小问题,所以理论上文件末尾可能有另一个“字段 12”。按照规范,它是“最后的价值获胜”,所以上面的短路可能(理论上)会给你一个不同的答案。然而!这是非常不可能的,如果您正在利用附加消息,您通常会知道。这根本不适用于大多数人。

【讨论】:

感谢您的帖子。这很有帮助。

以上是关于使用 Protobuf .net 反序列化单个结构字段的主要内容,如果未能解决你的问题,请参考以下文章

使用 ProtoBuf-Net,如何(反)序列化多维数组?

使用 protobuf-net 反序列化字典

使用 protobuf-net 反序列化不同的列表

为啥我不能使用 ProtoBuf-Net 正确反序列化我的对象?

使用 protobuf-net 反序列化 int& 类型

使用 protobuf-net 反序列化当前流位置的类型