当Windows XP和Vista中的磁盘策略设置为在硬盘上启用写缓存时,是否有方法刷新刚刚写入的文件,并确保其已提交到磁盘?
我想用C++编程实现这一点。
关闭文件确实会在应用程序级别执行刷新,但不会在操作系统级别执行刷新。如果在关闭文件后,但在操作系统刷新磁盘写缓存之前,PC断电,则即使文件已关闭,文件也会丢失。
.NET FileStream.Flush()不会为该文件内容刷新Windows缓存;Flush()只刷新.NET内部文件缓冲区。在.NET 4.0中,微软通过在Flush()中添加一个可选参数来解决这个问题,如果设置为true,则会调用FlushFileSystemBuffers。在.NET 3.5及以下版本中,您唯一的选择是通过pinvoke调用FlushFileBuffers。请参阅MSDN'sFileStream.Flush社区评论了解如何做到这一点。
您不应该在关闭文件时修复此问题。除非打开将FILE_FLAG_WRITE_THROUGH
传递给CreateFile()的文件,否则Windows将进行缓存。
您可能还想通过FILE_FLAG_NO_BUFFERING
;这个命令告诉Windows不要在缓存中保留字节的副本。
根据MSDN上的CreateFile文档,这比FlushFileBuffers()更有效。
另请参阅MSDN上的文件缓冲和文件缓存。
您还没有指定开发环境,所以:
.Net
IO流有一个.Flush
方法,可以执行您想要的操作。
Win32 API
有一个FlushFileBuffers
调用,它将文件句柄作为参数。
EDIT(基于OA的评论):FlushFileBuffers不需要管理权限;只有当传递给它的句柄是卷的句柄,而不是单个文件的句柄时,它才会执行此操作。
您还应该注意,即使在调用框架API的flush方法时,您的数据也可能不会被刷新到实际的磁盘。
调用flush方法只会告诉内核将其页面刷新到磁盘。但是,如果打开了磁盘写入缓存,则可以无限期地延迟实际写入过程。
为了确保数据写入物理层,您必须打开操作系统中的写缓存。在处理大量小型io操作时,这通常会带来高达一到两个数量级的性能损失。基于电池的支持(UPS)或接受刷新磁盘写缓存命令的磁盘是处理此问题的另一个选项。
从microsoft文档中,您将在COMMODE.OBJ中使用_flushall和链接来确保所有缓冲区都提交到磁盘。
请参阅此处:https://jeffpar.github.io/kbarchive/kb/066/Q66052/
当您最初使用fopen打开文件时,包括"c"模式选项作为最后一个选项:
fopen( path, "wc") // w - write mode, c - allow immediate commit to disk
然后,当您想强制刷新磁盘时,请调用
_flushall()
我们在呼叫之前打了这个电话
fclose()
我们遇到了你描述的确切问题,这种方法解决了它。
请注意,这种方法不需要管理权限,FlushFileBuffers
确实需要,正如其他人所提到的那样。
来自上述网站:
"Microsoft C/C++7.0版为fopen()引入了"C"模式选项作用当应用程序打开文件并指定"c"模式时当应用程序调用fflush()或_flushall()函数。"
您可以使用FileOptions.WriteThrough
标志打开/创建文件,这将导致文件绕过任何缓存直接写入磁盘。
例如
var file = File.Open(
"1.txt",
new FileStreamOptions
{
Options = FileOptions.WriteThrough
});
// - OR -
var file = new FileStream(
"1.txt",
FileMode.Create,
FileAccess.Write,
FileShare.None,
4096,
FileOptions.WriteThrough)