损坏的文件内容的原因

我在野外遇到一个反复出现的问题。

它有一个相当简单的XML文件,它每隔30分钟就会有一次转储。

数据文件通常很小 – 例如<5KB。

它没有locking文件 – 每次从头开始重新创build。

我很幸运地看到testing机器上发生的问题,我观察到的是该文件已损坏,并设置为“空”(即hex00)。 真奇怪的是,它的长度恰恰相反。

我在保存过程中非常小心:

  1. 我将xml写入到一个临时文件,并保存在同一个目录中
  2. 我用MOVEFILE_WRITE_THROUGH集执行一个Win32 MoveFile(),所以它应该阻塞,直到移动真的完成,移动文件来replace现有的数据文件

我甚至locking了一个Mutex,以确保这不是一个线程问题。

这种情况不会经常发生,例如1000个用户中有1个。

现在我已经观察到数据文件在写入过程中被电源故障或BSOD损坏,而且我已经看到文件的32kb全部为NULL。

但是看起来好像比我想象的要多,因为在写入过程中电源故障的可能性,特别是因为我使用MOVEFILE_WRITE_THROUGH。

有任何想法吗?

约翰


一些问题的答案:

  • 问:为什么不直接写入文件答:我避免了这个问题,使软件不易受电源故障的影响。 例如,你通过写文件和崩溃/ powerfail / BSOD一半,那么你肯定有一个损坏的文件。 执行临时文件写入然后移动是确保您尽可能执行primefaces文件操作的一种常用且简单的方法(当然,如果不使用NTFS特定的API,则尽可能合理)。 我应该说这个软件是一个归档/备份系统,所以我必须比其他应用程序更加关心数据的一致性。

  • 问:在正常操作中是否发生这种情况?

  • 答:由于这个问题是在野外发生的,我只用了一些线索,所以我不确定。 我可以说99.9%的时间软件可靠地工作。 我想这是我的问题的琐碎:这是BSOD /电源故障造成的随机不吉利还是它的错误?

  • 问:什么样的环境/操作系统:

  • 答:XP,Vista,7,Server 200X。 最有可能的NTFS,但可能是FAT32

  • 问:我在移动之前closures文件

  • 答:是的。 我使用C ++stream并在执行MoveFile之前调用close()

  • 问:还有哪些进程正在访问该文件?

  • 答:没有人pipe我。 显然,我不能控制病毒检查器,文件夹同步器等。该文件位于用户计算机的AppData \ Local文件夹中。

根据我的经验,这可能是由Windows中的文件缓存引起的。 您应该尝试使用CreateFile()FILE_FLAG_WRITE_THROUGH传入来保存文件。通过这种方式保存文件可以确保文件将落在硬盘上。

我wr了一个小程序来测试这个。 如果程序使用std::ofstream创建文件并使用MoveFileEx()MOVEFILE_WRITE_THROUGH来移动该文件,则在文件移动完成后立即关闭(不关闭)虚拟机几乎每次都会损坏文件; 否则,如果程序使用FILE_FLAG_WRITE_THROUGH CreateFile()来创建文件,并再次做同样的事情,文件没有损坏(我测试了大约10次,但没有发生)。

经过这些简单的测试,我认为你应该尝试使用FILE_FLAG_WRITE_THROUGH CreateFile()来解决你的问题。

更多信息:
文件缓存(Windows)
Windows内部,第6版,第11章缓存管理器

这里有一些想法:

  • 在重要信息之后或长时间不写之前冲洗流。
  • 确认没有其他实体正在写入文件。
  • 验证缓冲的数据不被其他代码覆盖。
  • 在长时间不写入的情况下关闭文件。