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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/383324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:23:27  来源:igfitidea点击:

How to ensure all data has been physically written to disk?

c#.netfilestreamflush

提问by Stefan Schultze

I understand that .NET FileStream's Flush method only writes the current buffer to disk, but dependent on Windows' disk driver and the hard disk firmware this is no guarantee that the data is actually physically written to disk.

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

Is there a .NET or Win32 method that can give me this guarantee? So if there is power loss one nanosecond after the call to this method comes back, I can still be sure that everything is OK?

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

采纳答案by Marc Gravell

Under Windows, look at FlushFileBuffers(Win32 API).

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

回答by Marc Gravell

Well, you could close the file... that would probably do it. In reality, with HAL abstraction, virtualization, and disk hardware now having more processing power and cache memory than computersdid a few years ago, you're going to have to live with hoping the disk does its job.

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

The transactional file system never really materialized ;-p Of course, you could perhaps look at using a database as a back end, and use the transaction system of that?

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

Aside: note that not all streams even guarantee to Flush()- for example, GZipStreametc retain a working buffer of uncommitted data even after a flush - the only way to get it to flush everythingis to Close()it.

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

回答by Ayresome

There's simply too many levels of abstraction to be absolutely sure that the data is written to the disc, right down to the hardware level.

抽象层次太多,无法绝对确保将数据写入磁盘,直到硬件层次。

Not brilliantly performant or foolproof, but how about re-opening the file once it is written in a seperate process and checking the size or contents?

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

回答by jimvfr

Stefan S. said:

Stefan S. 说:

I understand that .NET FileStream's Flush method only writes the current buffer to disk

我了解 .NET FileStream 的 Flush 方法只将当前缓冲区写入磁盘

No, .NET FileStream's Flush only writes the .NET buffers to the OS cache, it does not flush the OS cache to disk. Sadly the MSDN doc on this class doesn't say that. For .NET < 4.0, you'll have to call Flush + Win32's FlushFilebuffers:

不,.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);
}

For .NET 4.0, you can instead use the new flush(true) method. 11/09/2012 update: MS bug report heresays it's broken, then fixed, but doesn't say what version or service pack it was fixed in! Sounds like bug was if internal .NET FileStream buffer is empty, the Flush(true) did nothing??

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

回答by dave

I've noticed that the .NET 4 #Flush(true) doesn't actually write to the disk. We were having strange issues with corrupted data and I found this bug reporton the MS site:

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

The details tab for the bug report has a test program you can run that will show the issue;

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

  1. Write a bunch of data to disk
  2. fs.Flush(true). This takes no time (much faster than can possibly written to the disk).
  3. Use the win32 API FlushFileBuffers. This takes a long time.
  1. 将一堆数据写入磁盘
  2. fs.Flush(true). 这不需要时间(比可能写入磁盘快得多)。
  3. 使用 win32 API FlushFileBuffers。这需要很长时间。

I'm changing over to the win32 FlushFileBuffers call...

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

回答by MSH

The file data that's buffered in the file system cache to be written to disk. That data is normally lazily written, based on the position of the disk write head. Having a gigabyte of cached data is technically possible so it can take quite a while. If this is important to you then consider the FileOptions.WriteThroughoption instead.

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

回答by Mickey2

There is a simple answer to flushing the content of the buffer to disk. After your WriteAllText function, open file, close it, and reset it

here is an example

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

这是一个例子

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