如何确保所有数据都已物理写入磁盘?

时间:2008-12-20 13:32:06

标签: c# .net filestream flush

据我所知,.NET FileStream的Flush方法只将当前缓冲区写入磁盘,但依赖于Windows的磁盘驱动程序和硬盘固件,这并不能保证数据实际上是物理写入磁盘。

是否有.NET或Win32方法可以为我提供此保证?因此,如果在调用此方法后一纳秒之后出现断电,我仍然可以确定一切正常吗?

7 个答案:

答案 0 :(得分:15)

Stefan S.说:

  

据我所知,.NET FileStream的Flush方法只将当前缓冲区写入磁盘

不,.NET FileStream的Flush只将.NET缓冲区写入操作系统缓存,它不会将操作系统缓存刷新到磁盘。可悲的是,这个类的MSDN文档并没有这么说。对于.NET< 4.0,你必须调用Flush + Win32的FlushFilebuffers:

using System.Runtime.InteropServices;
. . .

// start of class:
[DllImport("kernel32", SetLastError=true)]
private static extern bool FlushFileBuffers(IntPtr handle);
. . .

stream.Flush();     // Flush .NET buffers to OS file cache.
#pragma warning disable 618,612 // disable stream.Handle deprecation warning.
if (!FlushFileBuffers(stream.Handle))   // Flush OS file cache to disk.
#pragma warning restore 618,612
{
  Int32 err = Marshal.GetLastWin32Error();
  throw new Win32Exception(err, "Win32 FlushFileBuffers returned error for " + stream.Name);
}

对于.NET 4.0,您可以使用新的flush(true)方法。 11/09/2012更新:MS错误报告here说它已损坏,然后修复,但没有说明它修复了哪个版本或服务包!听起来像bug是内部.NET FileStream缓冲区是空的,Flush(true)什么也没做?

答案 1 :(得分:8)

在Windows下,查看FlushFileBuffers(Win32 API)。

答案 2 :(得分:3)

好吧,你可以关闭文件...那可能会这样做。实际上,HAL抽象,虚拟化和磁盘硬件现在比几年前的计算机具有更多的处理能力和缓存内存,你将不得不忍受希望磁盘能够完成它的工作

事务性文件系统从未真正实现过;-p当然,您可以考虑使用数据库作为后端,并使用它的事务系统?

除此之外:请注意,并非所有流都保证Flush() - 例如,GZipStream等等即使在刷新后仍保留未提交数据的工作缓冲区 - 这是让它冲洗一切都是Close()

答案 3 :(得分:3)

我注意到.NET 4 #Flush(true)实际上并没有写入磁盘。我们遇到了数据损坏的奇怪问题,我在MS网站上发现了这个bug report

错误报告的详细信息选项卡有一个可以运行的测试程序,可以显示问题;

  1. 将一堆数据写入磁盘
  2. fs.Flush(true)。这不需要时间(比可能写入磁盘的速度快得多)。
  3. 使用win32 API FlushFileBuffers。这需要很长时间。
  4. 我正在转换到win32 FlushFileBuffers调用...

答案 4 :(得分:0)

要在文件系统缓存中缓冲以写入磁盘的文件数据。根据磁盘写头的位置,该数据通常是懒惰写入的。拥有一千兆字节的缓存数据在技术上是可行的,因此可能需要一段时间。如果这对您很重要,请考虑使用FileOptions.WriteThrough选项。

答案 5 :(得分:0)

  

有一个简单的答案可以将缓冲区的内容刷新到磁盘。   使用WriteAllText函数后,打开文件,将其关闭,然后将其重置

     

这是一个例子

My.Computer.FileSystem.WriteAllText(yourfilename, "hello", False, System.Text.Encoding.ASCII)
FileOpen(1, yourfilename, OpenMode.Input)
FileClose(1)
Reset()

答案 6 :(得分:-2)

只有太多的抽象级别才能绝对确保将数据写入光盘,直至硬件级别。

性能不是很出色或万无一失,但是如果文件在单独的过程中写入并检查大小或内容,那么如何重新打开文件呢?