c# - 错误:在解析完成之前遇到流结束,在 for 循环中使用 BinaryFormatter.Deserialize
问题描述
当我在 for 循环中使用使用 JsonUltility 的加载系统时遇到问题,它会引发如下错误:
“在解析完成之前遇到流结束”
保存和加载系统的代码是这样的:
类保存和加载系统的完整示例:
public void SaveParty(Player[] players, string nameFile)
{
Debug.Log("Saving!");
FileStream file = new FileStream(Application.persistentDataPath + nameFile, FileMode.OpenOrCreate);
try
{
// Binary Formatter
BinaryFormatter formatter = new BinaryFormatter();
// Serialize
for(int x = 0; x < players.Length; x++)
{
var json = JsonUtility.ToJson(players[x]);
formatter.Serialize(file, json);
}
}
catch (SerializationException e)
{
Debug.LogError("Error Saving: " + e.Message);
}
finally
{
file.Close();
Debug.Log(Application.persistentDataPath);
}
}
// Save Current Party Data
public void SaveCurrentParty()
{
// If exist will delete, and save again
if(FirstTimeSaving)
{
File.Delete(Application.persistentDataPath + NameFile[1]);
SaveParty(gameManager.CurrentParty, NameFile[1]);
}
// If not exist will save
if(!FirstTimeSaving)
{
SaveParty(gameManager.CurrentParty, NameFile[1]);
FirstTimeSaving = true;
}
}
// Load Party Data
public void LoadParty(Player[] party, string nameFile)
{
Debug.Log("Loading!");
FileStream file = new FileStream(Application.persistentDataPath + nameFile, FileMode.Open);
try
{
BinaryFormatter formatter = new BinaryFormatter();
// Error Here ↓
for(int i = 0; i < party.Length; i++)
{
JsonUtility.FromJsonOverwrite((string)formatter.Deserialize(file), party[i]);
}
}
catch (SerializationException e)
{
Debug.Log("Error Load: " + e.Message);
}
finally
{
file.Close();
}
}
而且我知道错误是在 LoadParty 中使用 JsonUtility 的 for 循环。
这就是我要保存的:
[System.Serializable]
public class Player : MonoBehaviour
{
// Stats
public int Hp;
public int Sp;
public int level;
public int St;
public int Ma;
public int Ag;
public int En;
public int Lu;
// Items
public MeleeWeapon Weapon;
// Skills
public List<Skills> skills = new List<Skills>();
}
解决方案
您试图FileStream
在循环中重复读取相同的内容。第一个操作读取文件并将位置推进到流的末尾。之后抛出异常,因为流中没有任何内容可供读取。
这发生在这里 - 它与JsonUtility
:
(string)formatter.Deserialize(file)
这会将整个流读取到最后。
这在您编写时不是问题,因为您序列化的每个对象都会附加到流中。
一种解决方案是序列化和反序列化整个Player[]
. 这样你只能从流中读取一次。当您打开文件时,您位于位置 0 - 流的开头。您阅读整个文件并反序列Player[]
化,而不是单个Player
对象。完成后,您已经阅读了整个流,并且拥有了所有数据。
我回避了是否使用二进制序列化的担忧。无论数据如何序列化,基本原则都适用。