Adequetely safe method of overwriting a save file?

非 Y 不嫁゛ 提交于 2020-01-02 19:39:09

问题


Using cstdio, what is the safest way of overwriting a file? 'safe' in this case meaning that there's no chance the file will become incomplete or corrupted; the file will either be the completely overwritten, or it will be the old file should something have gone awry.

I imagine the best way to do this, would be to create a temporary intermediate file, then overwrite the old file once that intermediate is complete. If that actually is the best way though, there's a few other problems that'd seem possible, if albeit rare.

  • How would I know to use this other file should the program quit while overwriting?
  • How would I know to NOT use the other file should the program quit during it's creation?
  • How would I know the original file or the intermediate is in an undefined state (since it may fail in a way that remains readable but the data it contains is subtly wrong)?

I imagine there's a single good practice for this, but I haven't been able to find it. This is for saved game data; there's only one file, and the entire file is overwritten every time as well, there are no partial overwrites or appending to worry about.


回答1:


As others have said, keep the existing file around, and write to a fresh file. If it's very important (that is, the user can't possibly recover the information), make sure that there is a "backup" file around as well (e.g. if your program saves abc.config, leave an abc.old.config or abc.backup [if you want guarantees that the name works everywhere, .cfg and .bak may be better choices]).

When you write the file, put some sort of endmarker in the file, so that you can be sure that the file is complete. If you want to avoid "user editing" of the file, you may also want to have a checksum of the content (sha1, md5 or similar). If the endmarker isn't there, or the checksum is wrong, then you know that the file is "bad", so don't use it. Go for the backup.

  1. Write the new conten to a temporary file (eg. fstream fout("abc.tmp");)
  2. Delete the backup file (if it exists) (e.g remove("abc.bak");)
  3. Rename the now old file to the backup name (e.g. rename("abc.cfg", "abc.bak");)
  4. Rename the new file to the old one (e.g. rename("abc.tmp", "abc.cfg");

For ALL steps (in particular writing the actual data), check for errors. You need to decide where it is OK to get errors and where it is not (remove of a file that doesn't exist is OK, for example, but if rename doesn't work you probably should stop, or you may end up with something bad).

When loading the file, check all steps, if it goes wrong, go back to the backup file.




回答2:


You should use a database management system that guarantees ACID for this. If you insist using flat files, you should write to a temp file, copy and replace the actual file when writing completes, and only delete the temp file when copy is successful. Also, call flush() on every write to the file.




回答3:


You should prevent the application to be closed while saving the data into the file. What you should do is load the old file, keep it in a variable - overwrite the data of the variable (in your app), and write it over the old one. Everything should take less than 1 second, so you shouldn't worry about closing your app while saving. Also, overwrite ONLY after you check if the operation is possible and the integrity of data is correct.



来源:https://stackoverflow.com/questions/18260899/adequetely-safe-method-of-overwriting-a-save-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!