保存到文件时如何确保数据不会被破坏?

时间:2011-10-31 17:49:45

标签: c# save corrupt-data

我对C#比较新,所以请耐心等待。

我正在编写一个需要可靠的业务应用程序(在C#,.NET 4中)。数据将存储在文件中。文件将被定期修改(重写),因此我担心某些事情可能出错(掉电,应用程序被杀死,系统冻结......),同时保存数据(我认为)会导致文件损坏。我知道没有保存的数据会丢失,但我不能丢失已保存的数据(因为损坏或......)。

我的想法是每个文件都有2个版本,每次都重写最旧的文件。然后,如果我的应用程序意外结束,至少有一个文件应该仍然有效。

这是一个好方法吗?还有什么我能做的吗? (数据库不是一个选项)

感谢您的时间和答案。

3 个答案:

答案 0 :(得分:10)

您可以使用“安全文件写入”技术:

,而不是“始终写入最旧的”

(假设您希望最终将数据保存到foo.data,并且具有该名称的文件包含先前的有效版本。)

  • 将新数据写入foo.data.new
  • foo.data重命名为foo.data.old
  • foo.data.new重命名为foo.data
  • 删除foo.data.old

在任何时候,总是至少获得一个有效文件,您可以告诉哪个文件只能从文件名中读取。这假设您的文件系统当然会原子地处理重命名和删除操作。

  • 如果存在foo.datafoo.data.new,请加载foo.data; foo.data.new可能会被破坏(例如写入期间断电)
  • 如果存在foo.data.oldfoo.data.new,则两者都应该有效,但事后很快就会死亡 - 您可能想要加载foo.data.old版本< / LI>
  • 如果foo.datafoo.data.old存在,那么foo.data应该没问题,但又出现了问题,或者可能无法删除文件。

或者,只需始终写入新文件,包括某种单调增加的计数器 - 这样您就不会因为写入错误而丢失任何数据。最好的方法取决于你写的是什么。

您也可以使用File.Replace,这基本上可以为您执行最后三个步骤。 (如果您不想保留备份,请在null中传递备份名称。)

答案 1 :(得分:4)

很多程序都使用这种方法,但通常会做更多的副本,以避免人为错误。

例如,Cadsoft Eagle(用于设计电路和印刷电路板的程序)最多可以为同一个文件创建9个备份副本,称之为file.b#1 ... file.b#9

强制安全性可以做的另一件事是散列:在文件末尾添加类似CRC32或MD5的散列。 打开它时,检查CRC或MD5,如果它们不匹配,则文件已损坏。 这也将强制您意外或按目的尝试使用其他程序修改您的文件。 这也将为您提供一种方法来了解硬盘驱动器或USB磁盘是否已损坏。

当然,保存文件操作越快,丢失数据的风险就越小,但您无法确定在写入期间或之后不会发生任何事情。

考虑到硬盘驱动器,USB驱动器和Windows操作系统都使用缓存,这意味着,如果你完成写入数据可能是操作系统或磁盘本身仍然没有将其物理写入磁盘。

你可以做的另一件事,保存到一个临时文件,如果一切正常你将文件移到真正的目标文件夹中,这将减少半文件的风险。

您可以将所有这些技巧混合在一起。

答案 2 :(得分:0)

原则上有两种流行的方法:

  • 使您的文件格式基于日志,即不要在通常的保存情况下覆盖,只需在最后添加更改或最新版本。

  • 写入新文件,将旧文件重命名为备份,并将新文件重命名为其位置。

第一个让您(方式)更多的开发工作,但如果您保存对大文件(用于执行此AFAIK的Word)的小更改,则还具有使保存更快的优势。