【发布时间】:2013-07-26 14:33:28
【问题描述】:
我的应用程序经常想要保存文件以便稍后再次加载。最近因为崩溃而倒霉,我想以这样一种方式编写操作,以保证我要么拥有新数据,要么拥有原始数据,但没有损坏的混乱。
我的第一个想法是按照以下方式做一些事情(保存名为 example.dat 的文件):
- 为目标目录指定一个唯一的文件名,例如例子.dat.tmp
- 创建该文件并将我的数据写入其中。
- 删除原始文件(example.dat)
- 将临时文件重命名(“移动”)到原来的位置(example.dat.tmp -> example.dat)。
那么在加载时应用程序可以遵循以下规则:
- 如果没有“example.dat”也没有“example.dat.tmp”,首先运行/新建项目,所以加载默认值/创建新文件。
- 如果“example.dat”且没有“example.dat.tmp”,则加载example.dat(正常负载情况)
- 如果存在“example.dat.tmp”,则为用户提供恢复数据的机会。如果“example.dat”也存在,请不要在没有明确用户常量的情况下覆盖它。
但是,经过一些研究,我发现除了可以使用文件刷新方法覆盖的操作系统缓存之外,一些磁盘驱动器仍然在内部缓存,甚至可能欺骗操作系统说它们已经完成, 所以 4. 可以完成,写入实际上并没有写入,如果系统宕机我已经丢失了我的数据...
我不确定磁盘问题实际上是否可以通过应用程序解决,但以上一般规则是否正确?我是否应该将文件的旧恢复副本保留更长时间,以确保有关这些事情的指导方针是什么(例如,可接受的磁盘使用情况、用户应选择的位置、放置此类文件的位置等)。
另外我应该如何避免用户和其他程序对“example.dat.tmp”的潜在冲突。我记得有时会从其他一些软件中看到“~example.dat”,这是一个更好的约定吗?
【问题讨论】:
-
重命名前无需删除旧文件。而且这种方式很常见(写入临时文件,然后将临时文件重命名为原始文件)。
-
在文件本身中有一些检查数据可以让您验证其完整性。在这种情况下,您可以自动处理“两个文件都存在”的情况——如果检查 tmp 文件表明它没有损坏,则使用它,否则使用 dat 文件。可以在打开文件时使用
FILE_FLAG_WRITE_THROUGH标志绕过写缓存。 -
@JoachimPileborg 但您通常需要先用
".bak"重命名目标。 -
@cdhowie 够了吗?该文档似乎表明它不是,但没有表明还需要什么。 (Windows 文档似乎表明它相当于 Unix 下的
O_DSYNC,但为了完全完整,您需要O_DSYNC | O_SYNC。) -
@JamesKanze This page 可能会有所帮助。