覆盖保存文件的安全方法?

2022-01-24 00:00:00 file save c++

使用 cstdio,覆盖文件最安全的方法是什么?在这种情况下,安全"意味着文件不可能变得不完整或损坏;该文件将被完全覆盖,或者如果出现问题,它将是旧文件.

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.

  • 如果程序在覆盖时退出,我怎么知道要使用这个其他文件?
  • 如果程序在创建过程中退出,我怎么知道不使用其他文件?
  • 我怎么知道原始文件或中间处于未定义状态(因为它可能会以某种方式失败仍然可读,但它包含的数据有细微的错误)?

我想这有一个好的做法,但我一直找不到.这是用于保存的游戏数据;只有一个文件,而且每次都会覆盖整个文件,不用担心部分覆盖或追加.

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.

推荐答案

正如其他人所说,保留现有文件,并写入新文件.如果它非常重要(即用户不可能恢复信息),请确保周围还有一个备份"文件(例如,如果您的程序保存了 abc.config,请离开abc.old.configabc.backup [如果您想保证该名称在任何地方都有效,.cfg.bak 可能是更好的选择]).

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]).

当你写文件的时候,在文件中加入某种结束标记,这样你就可以确定文件是完整的.如果您想避免用户编辑"文件,您可能还需要内容的校验和(sha1、md5 或类似).如果 endmarker 不存在,或者校验和错误,那么你就知道文件是坏的",所以不要使用它.去备份.

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. 将新内容写入临时文件(例如.fstream fout("abc.tmp");)
  2. 删除备份文件(如果存在)(例如 remove("abc.bak");)
  3. 将现在的旧文件重命名为备份名称(例如 rename("abc.cfg", "abc.bak");)
  4. 将新文件重命名为旧文件(例如 rename("abc.tmp", "abc.cfg");

对于所有步骤(尤其是写入实际数据),检查错误.您需要决定哪里可以出错,哪里不能出错(例如,remove 不存在的文件是可以的,但是如果 rename 没有'不工作,你可能应该停止,否则你可能会遇到不好的事情).

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.

相关文章