我正在使用 Delphi 和ReadDirectoryChangesW(在 a 中TThread)来检测特定文件夹何时发生更改。这工作得很好。我需要知道更改何时完成,以便我可以安全地对文件执行某些操作。

场景如下:我已将打印机映射到特定的文件名和文件夹(文件:本地端口c:\MonitorMe\prinfil.dat)。该文件夹中的唯一文件是该打印机文件。打印作业可以是单页,也可以是数百页 - 我必须等到“打印到文件”完成才能触发进一步的操作。我正在监视FILE_NOTIFY_CHANGE_SIZE-FILE_NOTIFY_CHANGE_LAST_WRITE所以我会定期收到文件仍在“打印到”的通知。

我正在寻找一种安全的方法来实际检测“打印”何时完成。我想我可以在表单中设置一个计时器,然后Synchronize(StillPrinting)在线程中调用。StillPrinting将停止并重新启动计时器,这样只有在大约 300 毫秒没有文件夹更改后,计时器才会执行 - 触发事件OnAfterPrintComplete这看起来很危险。

我可以寻找什么来确定文件保存是否已完成?


"File has been completed" is subjective - just think about it for 5 minutes and you'll come to the conclusion you're asking for something that rarely makes sense:

  • Speed of writing can vary: you might expect a file to be written in 2 seconds on one system while it takes 5 minutes on another.
  • Drawing the line: at which point do you consider a "write" to be completed and at which point are other writes appending to the existing file? Thing about logs where it can take i.e. 2 years until another write to that file occurs. Likewise your printer job/program can idle for 10 minutes for whatever reason but still access the file.
  • Modifications: what about a file that has been written from byte 1 to 52000 but afterwards bytes 10 to 19 are overwritten? When is that considered "completed"?
  • Even SetEndOfFile() only "cuts" (or extends) a file at a given point, but nobody knows if additional writes at any position will occur.

No. But there are various approaches to achieve the same:

  • Setting file attributes, i.e. R could signal that no more writes will occur. Because you as a consumer only want read access anyway. Of course, the "printer" has to set it.
  • 检查文件内容是否有有效的页脚,或者其任何格式是否不完整。这既要求您了解打印文件格式,又要求打印文件具有某种格式(而不仅仅是二进制流)。
  • 尝试在没有任何共享权限(甚至没有)的情况下打开文件FILE_SHARE_READ- 只要另一个进程访问该文件,这就会失败。您可以预期打印机作业不会多次打开/关闭文件(尽管这也是一种可能性)。
  • Abusing files as "writing complete" markers: if the file has been written, create another (empty) file whose existence alone signals that the other file is complete. As per your print job/program you could add another short/simple print task and judge that as soon as 2 files exist the one of interest must be completed (while the other is irrelevant to you).

@fpiette In fact, that's it - when I read the ms docs for FILE_NOTIFY_CHANGE_LAST_WRITE flag, I interpreted it as "every write" (last time it wrote, multiple writes per save). It actually means "last write as file is closed" - exactly what I want. I saved a 1300 page file, and it did what I needed. Thanks.

thanks for the comments - in this particular case, there is only one process writing to that particular file. It's a program printing shipping labels - I'm looking to replace the built-in label format with my own format (I can determine the actual data to print from a sql query). I have nothing but the print file to work with - I'm thinking maybe using FindFirstChangeNotificationW instead - when I see a change on the print file, then loop every 200ms checking to see if file can be opened.