3

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

我想最好的方法是创建一个临时中间文件,然后在中间完成后覆盖旧文件。如果这实际上是最好的方法,那么尽管很少见,但似乎还有一些其他问题是可能的。

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

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

4

3 回答 3

6

正如其他人所说,保留现有文件并写入新文件。如果它非常重要(也就是说,用户不可能恢复信息),请确保周围也有一个“备份”文件(例如,如果您的程序保存abc.config,请留下一个abc.old.configabc.backup[如果您想保证该名称无处不在,.cfg可能.bak是更好的选择])。

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

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

对于所有步骤(特别是写入实际数据),检查错误。您需要决定哪里可以出错,哪里不可以(remove例如,一个不存在的文件是可以的,但是如果rename不起作用,您可能应该停止,否则您可能会遇到一些不好的事情)。

加载文件时,检查所有步骤,如果出错,返回备份文件。

于 2013-08-15T20:42:31.647 回答
1

您应该使用保证 ACID 的数据库管理系统。如果您坚持使用平面文件,则应写入临时文件,写入完成后复制并替换实际文件,并仅在复制成功时删除临时文件。此外,调用flush()对文件的每次写入。

于 2013-08-15T20:14:03.447 回答
-3

在将数据保存到文件中时,您应该防止关闭应用程序。您应该做的是加载旧文件,将其保存在变量中 - 覆盖变量的数据(在您的应用程序中),然后将其覆盖旧文件。一切都应该不到 1 秒,因此您不必担心在保存时关闭应用程序。此外,仅在检查操作是否可行且数据完整性正确后才进行覆盖。

于 2013-08-15T20:16:09.390 回答