Delphi 如何检测文件的正确修改?

Delphi 如何检测文件的正确修改?,delphi,windows-7,file-io,delphi-xe,datemodified,Delphi,Windows 7,File Io,Delphi Xe,Datemodified,在一个例子中,我的一个问题是我的应用程序如何知道文件已被重写。我应该加上:“通过另一个应用程序”。首先,我尝试了在一个目录中报告更改,但在一个特定的文件中没有。好吧,我是不是遗漏了什么 现在我在计时器中使用FileAge,它每秒检查一个特定的文件是否已更改。当它工作时,它检测到两个修改,大约相隔13毫秒;当我将测试间隔更改为10秒时,此行为仍然存在。下面的代码是计时器的回调 procedure TAMI_Column_Selector.doWork (Sender: TObject); var

在一个例子中,我的一个问题是我的应用程序如何知道文件已被重写。我应该加上:“通过另一个应用程序”。首先,我尝试了在一个目录中报告更改,但在一个特定的文件中没有。好吧,我是不是遗漏了什么

现在我在计时器中使用FileAge,它每秒检查一个特定的文件是否已更改。当它工作时,它检测到两个修改,大约相隔13毫秒;当我将测试间隔更改为10秒时,此行为仍然存在。下面的代码是计时器的回调

procedure TAMI_Column_Selector.doWork (Sender: TObject);
var new_stamp: TDateTime;
begin
   if FileAge (remove_extension (FileName) + '.csv', new_stamp) then
   begin
      if (new_stamp <> FDateTimeStamp) then
      begin
         FDateTimeStamp := new_stamp;
         FTask.SyncCall (notify_user);
      end; // if
   end; // if
end; // doWork //
procedure TAMI\u Column\u Selector.doWork(发送方:TObject);
var新_戳记:TDateTime;
开始
如果文件年龄(删除扩展名(文件名)+'.csv',新的\u戳记),则
开始
如果(新的_戳记FDateTimeStamp),则
开始
FDateTimeStamp:=新的_戳记;
FTask.SyncCall(通知用户);
完如果
完如果
完嫁妆//
我的问题是:

  • 究竟是什么原因导致在上述代码中调用了两次
    notify_user
    ?文件系统的愚蠢错误或某些奇怪行为(例如,在打开和关闭文件时设置了修改日期)
  • 每秒钟检查一个文件是否已更改,感觉有点“浪费”。是否有类似于ShellNotify的东西只在特定文件被修改时通知我
  • 更新

    David Heffeman的答案(使用
    ReadDirectoryChangesW
    而不是轮询)是问题2的正确答案。但是,如问题1所述,在一次修改过程中(从用户的角度来看),它也会导致多次调用


    我比较了
    ReadDirectoryChangesW
    和轮询方法。使用两个文件(0.5MB和10MB)进行测试。在这两种情况下,轮询方法始终被调用两次,而
    ReadDirectoryChangesW
    被调用了几次(3到5次)。我将返回轮询方法并忽略第一个
    FileAge
    更改。我知道我不能确定这种行为是否一致,因为我不了解导致它的机制。

    我知道这不是对您的问题的直接回答,但我建议使用而不是轮询。

    删除扩展名(文件名)+'.csv'
    ->
    更改文件名(文件名,.csv')
    (无法解决您的问题)@davidheffman,谢谢,看来文件_NOTIFY(通知)(更改)(更改)(最后一次访问)可以解决这个问题。我会报告的。@GolezTrol,我总是很高兴有一些技巧可以让事情做得更好或更有效率,所以谢谢。它解决了我问题的一部分:不再投票。另一个问题仍然存在:事件被发送了好几次。可能打开、写入和关闭文件都会发送修改事件。因为这会导致一次又一次地读取一个大文件,这意味着读取一个不完整的文件。对此,您可能没有什么可以做的。您可能需要使用IPC与编写文件的应用程序进行通信,以便知道它何时真正完成了编写。这就是问题所在,我无法控制编写文件的应用程序。我将更深入地研究轮询方法:当它持续触发两次时,我将返回该方法。您可能需要设置dwNotifyFilter的属性。否则,对文件的写入将触发上次写入、上次访问和更改大小的事件。如果您将过滤器设置为FILE\u NOTIFY\u CHANGE\u LAST\u WRITE,它应该可以正常工作。@Pieter,我将过滤器设置为FILE\u NOTIFY\u CHANGE\u LAST\u WRITE作为唯一参数,但我仍然收到3条消息(打开、写入、关闭?)。不管怎样,谢谢你的解释,我只是在猜测。