起こったこと
System.IO.File.WriteAllBytesAsync("SaveData", data); のようなコードでセーブデータの書き込みを行っていました。
しかし、あるときちょうど書き込み中にクラッシュが発生し、SaveDataがサイズは正しいのにすべて0で埋まった状態になってしまいました。
(0埋めになるか0byteになるか、ここはなんでも起こりうる。)
原因
File.WriteAllText / File.WriteAllBytesは既存ファイルに対して上書きする場合、FileMode.Create相当でファイルを開くため
ファイルが存在する場合は内容を0byteに切り詰めてから書き込む(Truncate)挙動をするそうです。
(ここでFileMode.Createで開いているかららしい。)
.NETの内部実装やwin32 apiに疎いので細かい解説は詳しい方にお任せします。
適当なこと書いてるかもしれないのでツッコミください。
解決策
File.Replaceはatomicな操作らしいので、一旦一時ファイルにデータを書き出してからこれで置き換えてやります。 (参考:【C#】File.Replaceはatomicに更新を行うのか?)
こうすることで、なるべく安全にファイルを書き換えることができます。
File.Replaceが本当にatomicなら問題ないはずですが、読み込み時も元のファイルを読んでみて失敗したら.bakを読むのが良さそうです。