23

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

有没有 .NET 或 Win32 方法可以给我这个保证?所以如果在调用这个方法回来后一纳秒掉电,我仍然可以确定一切正常吗?

4

7 回答 7

17

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) 方法。2012 年 11 月 9 日更新:这里的 MS 错误报告说它已损坏,然后修复,但没有说明它是在哪个版本或服务包中修复的!听起来错误是如果内部 .NET FileStream 缓冲区为空,则 Flush(true) 什么也没做?

于 2010-10-21T22:14:20.080 回答
9

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

于 2008-12-20T13:36:34.697 回答
4

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

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

另外:请注意,并非所有流甚至都保证Flush()- 例如,GZipStream等即使在刷新之后仍保留未提交数据的工作缓冲区 - 让它刷新所有内容的唯一方法就是Close()它。

于 2008-12-20T13:33:50.770 回答
3

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

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

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

我正在切换到 win32 FlushFileBuffers 调用...

于 2012-05-18T23:01:40.947 回答
0

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

于 2016-09-21T14:23:57.153 回答
0

将缓冲区的内容刷新到磁盘有一个简单的答案。在您的 WriteAllText 函数之后,打开文件,关闭它,然后重置它

这是一个例子

My.Computer.FileSystem.WriteAllText(yourfilename, "hello", False, System.Text.Encoding.ASCII)
FileOpen(1, yourfilename, OpenMode.Input)
FileClose(1)
Reset()
于 2019-06-15T13:09:52.113 回答
-3

抽象级别太多了,无法绝对确保将数据写入磁盘,一直到硬件级别。

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

于 2008-12-20T19:05:10.603 回答