&引用;“可靠的”;使用.NET进行文件工作

&引用;“可靠的”;使用.NET进行文件工作,.net,file,io,.net,File,Io,应用程序需要一个计数器,该计数器的值将存储在文本文件中。有时它会在很短的时间间隔内发生 此测试代码经常重写文本文件(例如,每100毫秒一次): 它基本上工作正常,除了在我们的一个“可靠测试”中——在应用程序运行时停止计算机供电 令人吃惊的是,文件中没有任何文本(应该是数字),只有一两个空格字符 它试图写入的最后一个值丢失是可以理解的,但使文件不一致是非常糟糕的 尝试使用: createFile.Flush(); createFile.Close(); createFile.Dispose();

应用程序需要一个计数器,该计数器的值将存储在文本文件中。有时它会在很短的时间间隔内发生

此测试代码经常重写文本文件(例如,每100毫秒一次):

它基本上工作正常,除了在我们的一个“可靠测试”中——在应用程序运行时停止计算机供电

令人吃惊的是,文件中没有任何文本(应该是数字),只有一两个空格字符

它试图写入的最后一个值丢失是可以理解的,但使文件不一致是非常糟糕的

尝试使用:

createFile.Flush();
createFile.Close();
createFile.Dispose();

GC.Collect();
GC.WaitForPendingFinalizers();

没有帮助。

我认为最简单的方法是在Windows Vista/2008中使用事务文件系统:


也就是说,如果您是少数几个运行它的人之一…

您会想到各种选项:-

1) 保留当前文件的临时副本,例如重命名旧文件、写入新文件、删除旧文件(或使用临时名称写入新文件、删除旧文件、重命名新文件),但对于此类事情,您可能太频繁地写入文件

2) 通过定期清理写入多个文件,例如0001.txt、0002.txt、0003.txt等。。。每隔10秒删除除最后一个文件外的所有文件

3) 多次写入同一个文件,或者定期创建一个新文件,比如说每10分钟一次,再定期清理一次


4) 使用第三方日志平台,如log4net,它可能会防止断电等情况,并可以登录到各种目标,例如文件、数据库、IRC。您的文件缺少值,因为电源中断在Windows有机会将其刷新到磁盘之前关闭了它。您可以随意调用Flush、Close、Dispose等,但如果电源故障中断了呼叫,它们将无法运行。充其量,它们将减少漏洞窗口

我认为Adam Ralph的答案最适合在任何系统上运行。我投了他的票,但想加上我的$0.02,因为您的各种系统调用失败,以纠正这个问题。

关闭文件系统分区中的“性能优化”。您正在写入文件,但Windows并不费心将数据写入物理磁盘,而是将其保存在内存中,以便最终写入,即当有空闲时间时

显然你没有给它任何空闲时间:)

因此,关闭该标志,让Windows每次都将内容写入磁盘。这就像你在闪存驱动器上使用的同一个标志,以确保在你将数据从USB端口取出之前,数据已经被写入。您可以强制Windows使用API调用写入数据

或者你可以使用这个选项

显然,确保您的硬件也在写入数据-如果您有RAID卡,它将缓存数据写入本身,您需要一个电池来备份它,以确保数据被物理写入驱动器


不过,我想你不会对表演感到满意的。然后,您最好使用电池支持的raid卡写入磁盘。

谢谢大家的回答

听取他们的意见,目前的解决办法是:

使用(FileStream createFile=newfilestream(“Counter.txt”, FileMode.Create,FileAccess.Write,FileShare.None,8,FileOptions.WriteThrough) {}

由于最后一个参数-FileOptions.WriteThrough,所以包含了所有参数。其目的是避免使用各种现金、缓冲区、内存等


由于此解决方案不提供100%的保证(由于硬件原因:),因此保留了备份。事实上,每次写入操作都会执行两次—在原始文件和备份文件中。

FYI您不需要在using块中对文件流执行Close()类,Dispose会为您执行此操作。+1是第一个选项,而不是覆盖现有文件重命名它,然后写入新文件。然后,如果找不到主文件,请查看重命名为的备份(.bak或其他任何文件)。
createFile.Flush();
createFile.Close();
createFile.Dispose();

GC.Collect();
GC.WaitForPendingFinalizers();