“可靠”文件适用于.NET

时间:2009-01-29 11:58:09

标签: .net file io

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

此测试代码经常重写文本文件(f.e.每100毫秒):

int counter = 0;

while (true)
{
    WriteToFile(counter);
    counter++;
    Thread.Sleep(100);
}

private void WriteToFile(int counter)
{
    byte[] buffer = Encoding.ASCII.GetBytes(counter.ToString());
    using (FileStream createFile = new FileStream("Counter.txt", FileMode.Create))
    {
        createFile.Write(buffer, 0, buffer.Length);
        createFile.Close();
    }
}
除了我们的“可靠测试”之外,它的工作基本上都很好 - 在应用程序运行时停止计算机供电。

令人不快的是 - 在文件中没有任何文字(应该是数字)但只有一两个空格字符。

它尝试写入的最后一个值是可以理解的,但是使文件不一致真的很糟糕......

尝试使用:

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

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

无济于事。

5 个答案:

答案 0 :(得分:6)

我想到了各种选择: -

1)保留当前文件的临时副本,例如重命名旧文件,写入新文件,删除旧文件(或用临时名称写新文件,删除旧文件,重命名新文件),但也许你为这种事情经常写出文件

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

3)多次写入同一文件,也许每隔10分钟定期创建一个新文件,再定期清理。

4)使用第三方日志记录平台,例如log4net,它可能可以防止电力中断等事情,并且可以记录到各种目标,例如:文件,数据库,IRC

答案 1 :(得分:2)

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

http://www.michaelckennedy.net/blog/2007/12/07/SystemTransactionsAndWindowsVistaNTFSUpdated.aspx

http://msdn2.microsoft.com/magazine/2fc4ae05-f7b8-49d2-8630-f24bc9dfc2e6

也就是说,如果你是为数不多的人之一......

答案 2 :(得分:1)

您的文件缺少值,因为电源中断在Windows有机会将其清除到磁盘之前关闭了它。您可以根据需要调用Flush,Close,Dispose等,但如果电源故障中断了呼叫,它们将无法运行。充其量,他们将减少漏洞的窗口。

我认为Adam Ralph的答案是在任何系统上运行的最合适的答案。我投票支持他,但是想要在各种系统调用失败时加上我的0.02美元以纠正这个问题。

答案 3 :(得分:1)

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

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

因此,关闭该标志并使Windows每次都将内容写入磁盘。这就像您用于闪存驱动器的相同标志,以确保在将数据从USB端口拉出之前实际写入数据。您可以强制Windows使用FlushFileBuffers API调用来编写数据。

或者您可以使用FILE_FLAG_WRITE_THROUGH选项。

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

我认为你不会对表现感到满意。最好的办法是使用电池支持的raid卡写入磁盘。

答案 4 :(得分:0)

谢谢大家的答案。

听他们说现在的解决方案已成为:

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

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

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