我需要查看文件夹 - 文件将放入文件夹,文件副本可能需要几秒钟或几分钟才能完成。我已经阅读了有关SO的多个主题(Checking File sizes for changes,Detect file in use by other process)。这些都没有给出一个很好的答案。
轮询是“糟糕的”,但我怎么知道文件是否停止增加?具体来说,是否有“文件大小不变”或“文件完整”的通知? OS可以通知非活动(IOW,你如何证明是负面的?)。在我看来,逻辑上,一个人必须轮询一个文件,看看它是否没有改变。我还检查了SCEvents和UKKQueue,但两者都只通知了一个变化。 UKKQueue有一个“文件大小增加”的方法,但没有“文件大小没有增加方法”。
在没有轮询或使用sleep()的情况下,有没有办法检测文件副本完成?
答案 0 :(得分:0)
如果您可以控制正在传送的文件,请将它们复制到同一卷上的临时目录中,并在复制完成后再移动该文件。移动只是重新链接文件系统中的文件。然后,kqueue可以在文件存在时通知您。它的存在意味着整个文件就在那里。
顺便说一句,当你使用cocoa文件管理器API的“原子”版本时,这就是它在幕后的作用。
如果您没有控制权,并且只想监视文件,则使用kqueue在文件显示时通知您。随着文件的增长,队列将通知您它已被扩展。但是,它不知道某个其他应用程序是否已完成扩展文件,因此您仍需要某种计时器来检查更改。
我会在注册kqueue NOTE_EXTEND
事件的同时启动间隔计时器。我会跟踪上次看到NOTE_EXTEND
事件的时间,如果自上次计时器触发后我没有看过,我会认为文件已经停止扩展。
现在,您必须确定要使用的计时器值...以及是否要退出并继续查找“while”,但除非复制文件的应用程序通过“移动”执行此操作,或者除非它发送一个通知文件已被完全复制,你将不得不做一些类型的计时器,有一些任意的值......那时你就认为已经完成了。
显然,如果你能够适应第一个选项,事情要好得多,因为你有一种确定的方式来知道文件已经停止增长。
答案 1 :(得分:0)
这是我用来在本地监控文件的代码。我不确定这是否适合你。
int fileHander = open("/location/file", O_RDONLY);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
unsigned long mask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
__block dispatch_source_t source;
void (^changeHandler)(void) = ^{
unsigned long l = dispatch_source_get_data(source);
if (l & DISPATCH_VNODE_DELETE) {
printf("file deleted");
dispatch_source_cancel(source);
}
else {
printf("file data changed");
}
};
void (^cancelHandler)(void) = ^{
int fileHander = dispatch_source_get_handle(source);
close(fileHander);
};
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fileHander, mask, queue);
dispatch_source_set_event_handler(source, changeHandler);
dispatch_source_set_cancel_handler(source, cancelHandler);
dispatch_resume(source);