我知道.NET FileStream的Flush方法只会将当前缓冲区写入磁盘,但这取决于Windows的磁盘驱动程序和硬盘固件,无法保证数据实际上已经物理写入磁盘。
是否存在一种.NET或Win32方法可以给我这个保证?所以,如果在调用此方法返回后的一纳秒内出现停电,我仍然可以确信一切都是正常的?
我知道.NET FileStream的Flush方法只会将当前缓冲区写入磁盘,但这取决于Windows的磁盘驱动程序和硬盘固件,无法保证数据实际上已经物理写入磁盘。
是否存在一种.NET或Win32方法可以给我这个保证?所以,如果在调用此方法返回后的一纳秒内出现停电,我仍然可以确信一切都是正常的?
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日更新:微软的一个错误报告这里说它是有问题的,后来被修复了,但没有说修复在哪个版本或服务包中!听起来像是因为内部的.NET FileStream缓冲区为空时,Flush(true)不起作用?
嗯,你可以关闭文件……那可能就行了。实际上,由于HAL抽象、虚拟化和磁盘硬件现在具有比几年前的 计算机 更多的处理能力和缓存内存,所以你只能希望磁盘能够完成其工作。
事务性文件系统从未真正实现 ;-p 当然,你或许可以考虑使用数据库作为后端,并使用其事务系统?
另外:请注意,并非所有流甚至保证执行Flush()
——例如,GZipStream
等仍保留一份未提交数据的工作缓冲区,即使刷新之后也是如此——唯一的方法是Close()
它。
fs.Flush(true)
。 这不需要时间(比可能写入磁盘的速度快得多)。FlushFileBuffers
。 这需要很长时间。文件数据被缓存在文件系统缓存中,以便写入磁盘。这些数据通常是惰性写入的,取决于磁盘写入头的位置。缓存数据量可达1GB,因此可能需要相当长的时间。如果这对您很重要,请考虑使用FileOptions.WriteThrough
选项。
FILE_FLAG_WRITE_THROUGH
曾经在 SATA 硬盘上存在问题:https://disruptivesql.wordpress.com/2012/05/08/sata-and-write-through/
我不知道现在的情况如何,但在进一步研究和测试之前,我不会轻易相信它。 - Paul GrokeMy.Computer.FileSystem.WriteAllText(yourfilename, "hello", False, System.Text.Encoding.ASCII)
FileOpen(1, yourfilename, OpenMode.Input)
FileClose(1)
Reset()
有太多的抽象层次,无法绝对确定数据是否被写入到磁盘,甚至到硬件层面。
这种方法并不是非常高效或百分之百可靠,但可以在文件被写入后,在另一个进程中重新打开文件并检查大小或内容,如何?