问题记录:
今天碰到这个问题 在反序列化的时候 unity给我报了这个错误:
End of Stream encountered before parsing was completed.
以下是我C#序列化以及反序列化代码:
public void Save(PlayerSaveDataEnum type)
{
var p = Application.persistentDataPath + "/" + type + ".save";
IFormatter formatter = new BinaryFormatter();
Stream stream;
try
{
stream = new FileStream(p, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
if (stream == null)
{
return;
}
switch (type)
{
case PlayerSaveDataEnum.PlayerBaseData:
formatter.Serialize(stream, mPlayerData);
break;
case PlayerSaveDataEnum.MergeBookData:
formatter.Serialize(stream, mMergeBookData);
break;
case PlayerSaveDataEnum.MergeCoreData:
formatter.Serialize(stream, mMergeCoreData);
break;
case PlayerSaveDataEnum.ShopData:
formatter.Serialize(stream, mShopData);
break;
case PlayerSaveDataEnum.BingoData:
formatter.Serialize(stream,mBingoData);
break;
default:
//Debug.LogError("save type error");
break;
}
stream.Flush();
stream.Close();
stream.Dispose();
}
catch (Exception)
{
return;
}
}
反序列化:
public void Load(PlayerSaveDataEnum type)
{
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new FileStream(Application.persistentDataPath + "/" + type + ".save", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
{
try
{
if (stream.Length != 0)
{
stream.Position = 0;
switch (type)
{
case PlayerSaveDataEnum.PlayerBaseData:
mPlayerData = (BaseData)formatter.Deserialize(stream);
break;
case PlayerSaveDataEnum.MergeCoreData:
mMergeCoreData = (MergeCoreData)formatter.Deserialize(stream);
break;
case PlayerSaveDataEnum.MergeBookData:
mMergeBookData = (MergeBookData)formatter.Deserialize(stream);
break;
case PlayerSaveDataEnum.ShopData:
mShopData = (ShopData)formatter.Deserialize(stream);
break;
case PlayerSaveDataEnum.BingoData:
mBingoData = (BingoData)formatter.Deserialize(stream);
break;
default:
break;
}
}
else
{
switch (type)
{
case PlayerSaveDataEnum.PlayerBaseData:
mPlayerData = new BaseData();
break;
case PlayerSaveDataEnum.MergeCoreData:
mMergeCoreData = new MergeCoreData();
break;
case PlayerSaveDataEnum.MergeBookData:
mMergeBookData = new MergeBookData();
break;
case PlayerSaveDataEnum.ShopData:
mShopData = new ShopData();
break;
case PlayerSaveDataEnum.BingoData:
mBingoData = new BingoData();
break;
default:
break;
}
}
stream.Flush();
stream.Close();
stream.Dispose();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
在谷歌百度搜了半天搜到的解决方案无非是:
1.在变量以及类前加[SerializeField]以及[SerializeField]可序列化标志
我看我都加了,也没什么用。
2.读取文件流的时候指定位置: stream.Position = 0;或者 stream.Seek(0, SeekOrigin.Begin); 经过尝试未果。
之后我始终怀疑是我的存储的数据结构里有某些东西不能被序列化,然而有没有明确的Log信息,只能排除法一点一点剥离数据结构,看看内鬼是谁。
结果居然是这个东西:
Vector2
原来Vector系列是不能用这东西序列化的,具体原因我没有深究。
为了解决这种情况,我只能写了一个可序列化的平替:
/// <summary>
/// 可以序列化的Vector类 unity内置的vector没法序列化存储 可恶
/// </summary>
[Serializable]
public struct SerializeVector2
{
public int x;
public int y;
public SerializeVector2(int x,int y)
{
this.x = x;
this.y = y;
}
public int this[int index]
{
get
{
return index switch
{
0 => x,
1 => y,
_ => throw new IndexOutOfRangeException("Invalid SerializeVector2 index!"),
};
}
set
{
switch (index)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
default:
throw new IndexOutOfRangeException("Invalid SerializeVector2 index!");
}
}
}
}
其实就是把Vector代码复制过来,然后在类头部加上可序列化标志,然后之后存储部分不用vector 用这个SerializeVector2就好了。