3

現在Android(Monodroid)やWp7で動作しているアプリをMonoTouchでIOSに移植したいという課題に直面しています。

それは問題ではありませんが、protobuf-net フレームワークを使用してデータを逆シリアル化すると、次の例外が発生して常に失敗します。

ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354
  at ProtoBuf.ProtoReader.StartSubItem (ProtoBuf.ProtoReader reader) [0x00000] in <filename unknown>:0
  at ProtoBuf.BclHelpers.ReadGuid (ProtoBuf.ProtoReader source) [0x00000] in <filename unknown>:0
  at TpSerializer.Read (Application.Mobile.TpDataAccess.TimeEntryLoggingDao.Entities.ActiveTimeEntryDbo , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
  at TpSerializer.Deserialize (Int32 , System.Object , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType (ProtoBuf.ProtoReader reader, DataFormat format, Int32 tag, System.Type type, System.Object& value, Boolean skipOtherFields, Boolean asListItem, Boolean autoCreate, Boolean insideList) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.TryDeserializeList (ProtoBuf.Meta.TypeModel model, ProtoBuf.ProtoReader reader, DataFormat format, Int32 tag, System.Type listType, System.Type itemType, System.Object& value) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType (ProtoBuf.ProtoReader reader, DataFormat format, Int32 tag, System.Type type, System.Object& value, Boolean skipOtherFields, Boolean asListItem, Boolean autoCreate, Boolean insideList) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader reader, System.Type type, System.Object value, Boolean noAutoCreate) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type, ProtoBuf.SerializationContext context) [0x00000] in <filename unknown>:0
  at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type) [0x00000] in <filename unknown>:0
  at Application.Mobile.TpDataAccess.Core.CoreProtobufDao`2[System.Guid,Application.Mobile.TpDataAccess.TimeEntryDao.Entities.TimeEntryDbo].EnsureCollection () [0x00000] in <filename unknown>:0
  at Application.Mobile.TpDataAccess.TimeEntryDao.TimeEntryProtobufDao.PrepareAccess () [0x00000] in <filename unknown>:0
  at Application.Mobile.TpBusinessComponents.TimeEntryService.TimeEntryService.PrepareAccess () [0x00000] in <filename unknown>:0
  at App.TP.Mobile.AppDelegate.FinishedLaunching (MonoTouch.UIKit.UIApplication app, MonoTouch.Foundation.NSDictionary options) [0x00031] in /Users/Developer/Dropbox/Application Mobile/Application Mobile iOS Project/Application_Mobile/AppDelegate.cs:34
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
  at App.TP.Mobile.Application.Main (System.String[] args) [0x00000] in /Users/Developer/Dropbox/Application Mobile/Application Mobile iOS Project/Application_Mobile/Main.cs:17

問題は、エンティティやデータの保存方法を変更していないことです。

// and serialize
string file = Path.Combine(StoragePath, dataFileName);
using (var stm = new FileStream(file, FileMode.Create))
{
    foreach (var item in list)
        Serializer.Serialize(stm, item);
}

どのエンティティを読み取っても、失敗します。

string file = Path.Combine(StoragePath, dataFileName);
if (!File.Exists(file))
    return;

using (var stm = new FileStream(file, FileMode.Open))
{
    var list = (TClass[]) Serializer.Deserialize(stm, null, typeof(TClass[]));
    if (list == null)
        return;

    // transform array into dictionary
    for (int i = 0; i < list.Length; i++)
    {
        var entity = list[i];
        entities[primaryKeyFunction(entity)] = entity;
    }
}

以下の Protobuf-NET 環境を使用しています。

  • Protobuf-net r594 (unity dll)
  • 事前に作成されたシリアライザ

データの保存は問題ありませんが、読み込みは失敗します。どんな助けでも大歓迎です。

ありがとう - ゲルハルト

4

1 に答える 1

3

簡単でいいもの。としてFooシリアライズし、 としてデシリアライズしましFoo[]た。実際には、プロトコル バッファは追加可能な形式であるため、Serialize(同じファイルに) 繰り返し使用することで、実質的に 1 つのみを書き込みますFoo(ただし、ほとんどのメンバを繰り返し上書きします)。

基本的に、現在のコードを保持するには、代わりに を使用できます。SerializeWithLengthPrefixSerialize

foreach(var item in list)
{
    Serializer.SerializeWithLengthPrefix(stm, item,
        PrefixStyle.Base128, Serializer.ListItemTag);
}

単純に使用することもできます:

Serializer.Serialize(stm, list);

これらは両方とも意味的に同一です。どちらの場合も、得られるものは (密なバイナリ形式で):

[field 1, string]
[payload length of item 0]
[payload of item 0]
[field 1, string]
[payload length of item 1]
[payload of item 1]
...
[field 1, string]
[payload length of item n]
[payload of item n]

これはまさにDeserializeあなたがそれを言うときに探しているものですTClass[]

于 2012-10-18T13:33:16.403 に答える