我们目前面临的问题是,我们希望使用MonoTouch将当前在Android(Monodroid)和Wp7上运行的应用程序移植到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环境。
保存数据不是问题,但加载失败。 任何帮助都非常感谢。
由于 - 格哈德
答案 0 :(得分:3)
一个很好的简单。您已将其序列化为Foo
,并将其反序列化为Foo[]
。实际上,因为协议缓冲区是一种可附加格式,通过重复使用Serialize
(到同一个文件),你有效只写一个Foo
(但覆盖率最高)成员们反复)。
基本上,要保留当前代码,可以使用SerializeWithLengthPrefix
代替Serialize
,即
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[]