Обнаружение поврежденного файла при загрузке данных с использованием бинарного форматирования / десериализации - PullRequest
3 голосов
/ 27 июня 2019

Я работаю над видеоигрой, где я сохраняю / загружаю сохраненные игры плеера, используя бинарный формат c #.Это работает в 99% случаев, но иногда сохраненная игра пользователя как-то повреждается, и тогда игра не сможет прочитать файл.Если бы я мог определить, когда игра сталкивается с этой проблемой, я мог бы сказать ей, чтобы она загружала резервную копию последней удачной сохраненной игры, что было бы полезно для всех.

Вот как я загружаюсьданные:

       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 голосов
/ 27 июня 2019

Поскольку 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;

Попробуйте также онлайн .

0 голосов
/ 27 июня 2019

ну, вы должны открыть файл, чтобы проверить, открывается он или нет.что вы можете сделать, это сделать функцию, которая проверяет, можно ли открыть файл или нет -

Для проверки поврежденного файла

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;
}
...