使用binaryformatter /反序列化加载数据时检测到损坏的文件

时间:2019-06-27 08:45:08

标签: c# serialization binaryformatter

我正在开发一个视频游戏,该游戏使用C#的binaryformatter保存/加载玩家的savegame。这在99%的时间内都有效,但是有时用户的savegame会以某种方式被破坏,然后游戏将无法读取文件。但是,如果我能检测到游戏何时遇到此问题,我可以告诉它加载上一个良好的savegame的备份副本,这对每个人都有帮助。

这是我加载数据的方式:

       if (File.Exists(Application.persistentDataPath + "/" + saveLoad.saveFileName))
       {

           BinaryFormatter bf = new BinaryFormatter();
           FileStream file = File.Open(Application.persistentDataPath + "/" + saveLoad.saveFileName, FileMode.Open);
           saveLoad.savedGames = (List<savedGame_latest>)bf.Deserialize(file);
           file.Close();
           success = true;

       }

顺便说一句,这是游戏加载损坏的文件时的错误:

EndOfStreamException: Failed to read past end of stream

有什么想法吗?我想要的基本上是系统检测“哎呀,那是损坏的”,然后被分流以尝试加载最后一个安全备份的方法。

2 个答案:

答案 0 :(得分:0)

好,您必须打开文件以检查它是否正在打开。 您可以做的是建立一个检查文件是否可以打开的功能-

  

要检查损坏的文件

protected virtual bool IsFileCorrupted(FileInfo file)
{
    FileStream stream = null;

    try
    {
        stream = File.Open(FileMode.Open, FileAccess.Read, FileShare.None);
    }
    catch (IOException)
    {
       // File is corrupted
        return true;
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }

    //file is not corrupted
    return false;
}

答案 1 :(得分:0)

由于BinaryFormatter停止读取流后,您可以在保存的内容之后简单地添加一些哈希或校验和值,而不会破坏功能。

仅捕获EndOfStreamException只会检测到一个可能的损坏。

保存(hashAlg可以是任何HashAlgorithm实现):

new BinaryFormatter().Serialize(stream, savegame); // regular data
var hash = hashAlg.ComputeHash(stream.ToArray());
stream.Write(hash, 0, hash.Length); // hash

并加载:

int hashLength = hashAlg.HashSize / 8; // get hash size in bytes
var bytes = stream.ToArray();
hash = hashAlg.ComputeHash(bytes, 0, (int)stream.Length - hashLength);
if (!hash.SequenceEqual(bytes.Skip(bytes.Length - hashLength)))
    throw new ArgumentException("Savegame Corrupted"); // gotcha!
savegame = (SaveGame)new BinaryFormatter().Deserialize(stream);
return savegame;

也尝试online