经常有应用程序需要保存文件以便以后加载。最近遇到了一次崩溃,我希望以这样的方式编写操作,以确保我要么有新数据,要么有原始数据,但不会出现损坏的混乱。
我的第一个想法是按以下方式执行(保存名为example.dat的文件):
1. 为目标目录创建唯一的文件名,例如example.dat.tmp。 2. 创建该文件并将数据写入其中。 3. 删除原始文件(example.dat)。 4. 将临时文件重命名(“移动”)到原始文件所在位置(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”,这是更好的约定吗?
我的第一个想法是按以下方式执行(保存名为example.dat的文件):
1. 为目标目录创建唯一的文件名,例如example.dat.tmp。 2. 创建该文件并将数据写入其中。 3. 删除原始文件(example.dat)。 4. 将临时文件重命名(“移动”)到原始文件所在位置(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”,这是更好的约定吗?
FILE_FLAG_WRITE_THROUGH
标志来绕过写缓存。 - cdhowieO_DSYNC
,但为了完整性,您需要O_DSYNC | O_SYNC
。) - James Kanzefsync(fd)
可以在某些 Unix 系统上工作,包括 Solaris 和 Linux——只有在定义了_POSIX_SYCHRONIZED_ID
时,Posix 才需要它。) - James Kanze