问题
I've started to convert our Unity/iOS game to save state with Protobuf-net. It looked like things were working OK, until I added this instance variable to GameState
[ProtoMember(10)]
public List<Unit> fUnits;
Unit is
[ProtoContract]
[ProtoInclude(21, typeof(ArtilleryUnit))]
[ProtoInclude(22, typeof(CavalryArtilleryUnit))]
[ProtoInclude(23, typeof(CavalryUnit))]
[ProtoInclude(24, typeof(InfantryUnit))]
[Serializable]
public class Unit : IActionHandler
This is the first subclass I've serialized. I'm testing my code by deserializing right after writing
using (Stream memoryStream = new MemoryStream()) {
byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);
memoryStream.Write(data, 0, data.Length);
memoryStream.Position = 0;
WBTSSerializer deserializer = new WBTSSerializer();
testState = new GameState();
deserializer.Deserialize(memoryStream, testState, typeof(GameState));
}
and I get
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.SkipField () [0x00000] in <filename unknown>:0
at WBTSSerializer.Read (wbts.Unit , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
at WBTSSerializer.Read (wbts.GameState , ProtoBuf.ProtoReader ) [0x00000] in <filename unknown>:0
at WBTSSerializer.Deserialize (Int32 , System.Object , ProtoBuf.ProtoReader ) [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 wbts.Game.SaveGame (System.String filename) [0x000c1] in /Users/david/Shenandoah/WBTS/wbts/wbts/Game.cs:620
Needless to say, I've checked for overwriting (it's a brand new file). And, if I take out the ProtoMember(10), it won't throw.
If I take out the ProtoInclude lines, I get an error about the subclasses. And, if I take out ProtoMember within Unit, it still throws.
If it matters, I am currently just running this from Xamarin (on Mac OS X — I'm an iOS developer). But that's just for ease of testing, I have managed to hit Protobuf-net with enough sticks to make it run on an iPad.
回答1:
My eye is drawn immediately to:
byte[] data = System.Text.Encoding.UTF8.GetBytes(readText);
Protobuf data is not text, and is not UTF-8 (although strings inside protobuf data are UTF-8, by coincidence) - therefore "decoding" it (wrong word, really) via UTF8 will guarantee you corrupt data. The preferred way to deal with protobuf data is as binary - for example, a byte[] - much like you would with image data etc. However, if you are required to store or transport it in a text form, then Convert.ToBase64String and Convert.FromBase64String are appropriate mechanisms to translate between text and binary. Please see the first section of How many ways can you mess up IO? for more information.
来源:https://stackoverflow.com/questions/24611339/using-protobuf-net-i-get-an-exception-about-an-unknown-wire-type-with-listsubc