C# 如何确保所有数据都已物理写入磁盘?
我知道.NET FileStream的Flush方法仅将当前缓冲区写入磁盘,但这取决于Windows的磁盘驱动程序和硬盘固件。这并不能保证数据实际写入磁盘C# 如何确保所有数据都已物理写入磁盘?,c#,.net,filestream,flush,C#,.net,Filestream,Flush,我知道.NET FileStream的Flush方法仅将当前缓冲区写入磁盘,但这取决于Windows的磁盘驱动程序和硬盘固件。这并不能保证数据实际写入磁盘 有没有一个.NET或Win32方法可以给我这个保证?因此,如果在调用此方法后的一纳秒内出现断电,我仍然可以确保一切正常?好的,您可以关闭该文件。。。那可能就行了。事实上,随着HAL抽象、虚拟化和磁盘硬件现在比几年前的计算机拥有更多的处理能力和缓存,你将不得不希望磁盘能完成它的工作 事务性文件系统从未真正实现-p当然,您可以考虑使用数据库作为后
有没有一个.NET或Win32方法可以给我这个保证?因此,如果在调用此方法后的一纳秒内出现断电,我仍然可以确保一切正常?好的,您可以关闭该文件。。。那可能就行了。事实上,随着HAL抽象、虚拟化和磁盘硬件现在比几年前的计算机拥有更多的处理能力和缓存,你将不得不希望磁盘能完成它的工作 事务性文件系统从未真正实现-p当然,您可以考虑使用数据库作为后端,并使用其事务系统
旁白:请注意,并不是所有流都能保证
Flush()
-例如,GZipStream
等即使在刷新之后也会保留一个未提交数据的工作缓冲区-让它刷新所有内容的唯一方法是关闭()
它。在Windows下,查看(Win32 API).有太多的抽象级别,无法绝对确保数据写入光盘,一直到硬件级别
虽然没有出色的性能或万无一失,但如果在单独的过程中写入文件并检查其大小或内容,如何重新打开该文件?Stefan S.说:
我知道.NET FileStream的Flush方法只将当前缓冲区写入磁盘
否,.NET FileStream的刷新只将.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);
}
对于.NET4.0,您可以改为使用新的flush(true)方法。
2012年9月11日更新:MS bug报告称其已损坏,然后已修复,但未说明修复的版本或服务包!听起来这个错误是因为如果内部.NET FileStream缓冲区为空,刷新(true)什么也没做???我注意到.NET 4#Flush(true)实际上并没有写入磁盘。我们在损坏的数据方面遇到了奇怪的问题,我在MS站点上发现: bug报告的details选项卡有一个测试程序,您可以运行该程序来显示问题
fs.Flush(true)
。这不需要时间(比可能写入磁盘的速度快得多)FlushFileBuffers
。这需要很长时间我正在切换到win32 FlushFileBuffers调用 缓冲在文件系统缓存中以写入磁盘的文件数据。根据磁盘写入头的位置,该数据通常是延迟写入的。拥有千兆字节的缓存数据在技术上是可能的,因此可能需要相当长的时间。如果这对你很重要,那么考虑<代码>文件选项。 将缓冲区的内容刷新到磁盘有一个简单的答案。 在执行WriteAllText函数之后,打开文件,关闭它,然后重置它 这里有一个例子
从技术上讲,对数据库进行写入时,不能保证断电或其他灾难性故障不会以某种方式丢失写入或损坏数据库,尽管它比简单的文件系统写入更有可能存活。是的,但您可以包装“将此标记为完成”和“结果如下”同时transaction@cletus如果一个数据库系统不能保证它被破坏(至少我认为是一个不破坏酸的DBMS)或者运行在一个破碎的系统(OS,硬件,任何东西)上。谢谢:我已经很快地完成了一个性能测试和文件流。FLUSEH()是太快而不是真的。FileStream的SafeFileHandle上的FlushFileBuffers与我预期的一样慢(在测试中比Flush()慢100倍),我发现调用FlushFileBuffers会导致异常()。在.NET4下,按照@jimvfr()的建议调用FileStream.Flush(true)更容易、更安全。文件数据缓冲在文件系统缓存中,以写入磁盘。根据磁盘写入头的位置,该数据通常是延迟写入的。拥有千兆字节的缓存数据在技术上是可能的,因此可能需要相当长的时间。如果这对你很重要,那么就考虑FielopOs.WrreEnter选项。还有一种方法可以将这个逻辑应用到注册表中吗?那是毫无意义的,因为它不能保证数据已经被物理地写到磁盘上。重新打开请求和其他任何请求一样,都会经过缓存层。这也被证明是无效的。操作系统仍然会缓存。@trevster344,你有这方面的来源吗?@Matt
FILE\u FLAG\u WRITE\u THROUGH
过去常常被SATA驱动器破坏:我不知道当前的情况,但如果没有进一步的研究和测试,我不会相信它。fs.Flush(true)对我来说很好。Windows 10 x64创建者更新.NET 4。5@jjxtra:您是否使用网络服务器进行了测试,并实际拔出了插头?@Joshua nope,仅使用本地文件系统进行了测试,因此无法对此进行说明scenario@jjxtra:除非拔掉磁盘插头导致磁盘出现故障,否则它似乎可以工作。您需要网络服务器知道是您触发了比赛。
My.Computer.FileSystem.WriteAllText(yourfilename, "hello", False, System.Text.Encoding.ASCII)
FileOpen(1, yourfilename, OpenMode.Input)
FileClose(1)
Reset()