13

このスレッドや他のソースからの情報に従って、openstreetmap pbf ファイルの逆シリアル化を適切に機能させようとしています。

Protobuf-net オープン ストリート マップのデシリアライズ

現在、r480 の protobug dll を使用しています。protogen を使用して、osm proto から csharp クラス ファイルを作成しましたが、ストリームから読み込もうとしているコードのこのポイントに到達すると、次のようになります。

BlockHeader header;
using (var tmp = new LimitedStream(file, length))
{
    header = Serializer.Deserialize<BlockHeader>(tmp); // exception occurs here
}

次の例外がスローされます。

InnerException: System.InvalidOperationException
Message=Type is not expected, and no contract can be inferred: BlockHeader
Source=protobuf-net
StackTrace:
  at ProtoBuf.Meta.TypeModel.ThrowUnexpectedType(Type type) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 1115
  at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, Int32 tag, Type type, Object& value, Boolean skipOtherFields, Boolean asListItem, Boolean autoCreate, Boolean insideList) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 848
  at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 582
  at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 506
  at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 488
  at ProtoBuf.Serializer.Deserialize[T](Stream source) in C:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 69
  at OsmParserDemo.MainWindow.OsmParse() in C:\Users\crussell\Documents\Visual Studio 2010\Projects\OsmParseMadness\OsmParserDemo\MainWindow.xaml.cs:line 57
  at OsmParserDemo.MainWindow..ctor() in C:\Users\crussell\Documents\Visual Studio 2010\Projects\OsmParseMadness\OsmParserDemo\MainWindow.xaml.cs:line 28

そのため、コード構造を protobuf-net の例の構造と比較すると、各メンバーの識別に関して何かが欠けている可能性があるという印象を受けます。これは正しいですか、それとも私はこれで宇宙に出ていますか? どんな助けやヒントも大歓迎です!

編集: 生成された FileFormat.cs クラスからの BlockHeader のスニペットを次に示します。

ブロックヘッダー

4

2 に答える 2

17

コード ファイルを追加すると、すべてが明らかになります。使用しているライブラリは、スタック トレースに基づいて、protobuf-net です。しかし、その .cs ファイルはprotobuf-net とは何の関係もありません。まあ、ほとんど。

ご覧のとおり、(少なくとも) 2 つの c#/.net protobuf 実装があり、それらを混同していると思います。

  • protobuf-csharp-portは Jon Skeet によるもので、Java バージョンを直接移植したものです。つまり、同じ設計原則と API に従っています。C# と Java の両方で作業している場合は魅力的です。
  • protobuf-netは私によるもので、慣用的な .NET を目指した最初の原則からの実装です。つまり、既存の型 (基本的に 、 など) に対してコード ファーストで動作するXmlSerializerだけDataContractSerializerでなく、サポートもサポートします。必要に応じて .proto からの使用

紛らわしいことに、どちらも「protogen」と呼ばれるコード生成ツールを備えています。私の知る限り、この命名の一致は、計画 (良いか悪いか) ではなく、単なる自然な収束/一致でした。

protobuf-csharp-port の protogen から生成された c# ファイルは、protobuf-csharp-port ライブラリで動作します。

protobuf-net の protogen から生成された c# ファイルは、protobuf-net ライブラリで動作します。

以下は、protobuf-net で生成されたバージョンBlockHeaderです。

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// Generated from: Foo.proto
namespace ConsoleApplication9
{
  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Blob")]
  public partial class Blob : global::ProtoBuf.IExtensible
  {
    public Blob() {}


    private byte[] _raw = null;
    [global::ProtoBuf.ProtoMember(1, IsRequired = false, Name=@"raw", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] raw
    {
      get { return _raw; }
      set { _raw = value; }
    }

    private int _raw_size = default(int);
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"raw_size", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    [global::System.ComponentModel.DefaultValue(default(int))]
    public int raw_size
    {
      get { return _raw_size; }
      set { _raw_size = value; }
    }

    private byte[] _zlib_data = null;
    [global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"zlib_data", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] zlib_data
    {
      get { return _zlib_data; }
      set { _zlib_data = value; }
    }

    private byte[] _lzma_data = null;
    [global::ProtoBuf.ProtoMember(4, IsRequired = false, Name=@"lzma_data", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] lzma_data
    {
      get { return _lzma_data; }
      set { _lzma_data = value; }
    }

    private byte[] _bzip2_data = null;
    [global::ProtoBuf.ProtoMember(5, IsRequired = false, Name=@"bzip2_data", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] bzip2_data
    {
      get { return _bzip2_data; }
      set { _bzip2_data = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }

  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"BlockHeader")]
  public partial class BlockHeader : global::ProtoBuf.IExtensible
  {
    public BlockHeader() {}

    private string _type;
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"type", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public string type
    {
      get { return _type; }
      set { _type = value; }
    }

    private byte[] _indexdata = null;
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"indexdata", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] indexdata
    {
      get { return _indexdata; }
      set { _indexdata = value; }
    }
    private int _datasize;
    [global::ProtoBuf.ProtoMember(3, IsRequired = true, Name=@"datasize", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    public int datasize
    {
      get { return _datasize; }
      set { _datasize = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }

}

結論:

protobuf-net protogen を使用するか、protobuf-csharp-port ライブラリを使用します。ミックスアンドマッチはありません。

于 2012-07-19T19:54:09.420 に答える
3

このコードを実行すると、次のようなエラーが発生しました。

public IEnumerable<T> Deserialize<T>(string path)
{
    using (var stream = File.Open(path, FileMode.Open, FileAccess.Read))
    {
        var item = Serializer.Deserialize<IEnumerable<T>>(stream);
        return item;
    }
}

問題に変更IEnumerable<T>すると消えました。List<T>ProtoBuff はインターフェイスについて何も知らないと思います。逆シリアル化する非抽象/インターフェイス タイプを指定する必要があります。

UPD:結論: オブジェクトがシリアル化された型に逆シリアル化する必要があります。基本型なし。

于 2013-07-09T16:19:58.213 に答える