其他分享
首页 > 其他分享> > CodeGo.net>如何使用protobuf-net回读附加对象?

CodeGo.net>如何使用protobuf-net回读附加对象?

作者:互联网

我使用protobuf-net序列化将实时事件附加到文件流中.如何将所有保存的对象流回进行分析?我不想使用内存中的集合(因为它会很大).

private IEnumerable<Activity> Read() {
  using (var iso = new IsolatedStorageFileStream(storageFilename, FileMode.OpenOrCreate, FileAccess.Read, this.storage))
  using (var sr = new StreamReader(iso)) {
    while (!sr.EndOfStream) {
      yield return Serializer.Deserialize<Activity>(iso); // doesn't work
    }
  }
}

public void Append(Activity activity) {
  using (var iso = new IsolatedStorageFileStream(storageFilename, FileMode.Append, FileAccess.Write, this.storage)) {
    Serializer.Serialize(iso, activity);
  }
}

解决方法:

首先,我需要讨论protobuf格式(通过Google,而不是protobuf-net专用).根据设计,它是可附加的,但带有append === merge.对于列表,这意味着“附加为新项目”,但是对于单个对象,这意味着“合并成员”.其次,由于上述原因,protobuf中的根对象永远不会终止-“ end”很简单:当您用完传入数据时.第三,直接的后果是-字段不需要以任何特定顺序排列,通常会被覆盖.因此:如果您只是多次使用Serialize,然后读回数据:您将只有一个对象,该对象基本上具有流中最后一个对象的值.

但是,您想做的是很常见的情况.因此,protobuf-net通过包含SerializeWithLengthPrefix和DeserializeWithLengthPrefix方法来帮助您.如果使用这些代替序列化/反序列化,则可以正确解析单个对象.基本上,长度前缀限制了数据,以便仅读取每个对象的确切数量(而不是读取到文件的末尾).

我强烈建议(作为参数)使用tag === field-number === 1和base-128前缀样式(一个枚举).除了使数据始终完全符合protobuf标准(包括前缀数据)之外,这还将使使用附加的辅助方法(DeserializeItems)变得容易.这将通过迭代器块公开每个连续的对象,从而使高效读取大型文件而无需一次存储所有内容.它甚至可以与LINQ一起使用.

还有一种使用API​​的方法来选择性地解析/跳过文件中的不同对象-例如,跳过前532条记录而不处理数据.让我知道您是否需要一个例子.

如果您已经有很多数据已经使用Serialize而不是SerializeWithLengthPrefix进行存储-那么可能仍然可以通过使用ProtoReader来检测字段编号何时回绕来解密数据:含义,给定的字段“ 1、2 ,4、5、1、3、2、5”-我们大概可以得出结论,那里有3个对象,并据此进行解密.同样,让我知道您是否需要特定的示例.

标签:protobuf-net,c
来源: https://codeday.me/bug/20191122/2063071.html