如何强制文件刷新

How to force file flushing

本文关键字:刷新 文件 何强制      更新时间:2023-10-16

假设我有以下代码:

#include <chrono>
#include <fstream>
#include <thread>
int main()
{
  std::ofstream f("test.log");
  int i = 0;
  while (true)
  {
    f << i++;
    f.flush();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
}

(请注意,每次写入操作后我都有一个flush调用)

我注意到这个应用程序不会更新"test.log"文件的"上次修改时间"answers"大小"属性,除非我右键单击这个文件或打开它

我想这是由于内部缓冲(系统不想进行像实际磁盘I/O这样耗时的操作,除非被迫这样做)。我说得对吗?

我需要编写一个应用程序来监视其他应用程序创建的日志文件中的更改(我无法更改它们)。起初,我想到了C#中的FileSystemWatcher类,但我注意到它有同样的行为(除非文件在源应用程序中关闭,或者在Windows资源管理器中右键单击该文件,否则它不会触发相应的事件)。那我该怎么办?尽可能频繁地为我想要查找的每个文件调用像GetFileAttributes这样的WinAPI函数?

这里有两个独立的东西。首先,文件MFT记录(相当于inode)上最后一次修改的时间在每次写入时都会更新

然而,FindFirstFile和好友返回的信息不是来自文件,而是来自目录项中缓存的信息。每当关闭通过该目录项打开的文件时,就会更新此缓存。这是大多数应用程序显示的信息,如Windows资源管理器和命令提示符DIR命令。

如果您想知道文件何时更新,您需要执行相当于Unix stat操作的操作,该操作读取MFT记录(inode)。这需要打开文件的句柄,调用GetFileInformationByHandle并再次关闭句柄。

第二件事是有充分的理由不这样做。如果一个程序正在写入一个文件,它可能已经完成了写入过程的一半。因此,文件可能处于无效(损坏)状态。若要确保文件处于有效状态,您应该等待文件关闭。这就是你知道文件现在可以查看的方式。

一旦写入程序完成了对文件的写入,目录条目将被更新,FileSystemWatcher将显示该文件。

如果您绝对确定要查看仍在写入过程中的文件的通知,那么您可以查看USN更改日志作为一个选项。我不知道这是否比目录条目更及时,你必须对此进行调查。