首页 > 解决方案 > 错误:在解析完成之前遇到流结束,在 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>();
}

标签: c#jsonunity3dload

解决方案


您试图FileStream在循环中重复读取相同的内容。第一个操作读取文件并将位置推进到流的末尾。之后抛出异常,因为流中没有任何内容可供读取。

这发生在这里 - 它与JsonUtility

(string)formatter.Deserialize(file)

这会将整个流读取到最后。

这在您编写时不是问题,因为您序列化的每个对象都会附加到流中。

一种解决方案是序列化和反序列化整个Player[]. 这样你只能从流中读取一次。当您打开文件时,您位于位置 0 - 流的开头。您阅读整个文件并反序列Player[]化,而不是单个Player对象。完成后,您已经阅读了整个流,并且拥有了所有数据。

我回避了是否使用二进制序列化的担忧。无论数据如何序列化,基本原则都适用。


推荐阅读