观察文件大小的变化

时间:2014-05-07 19:37:40

标签: objective-c cocoa

我需要查看文件夹 - 文件将放入文件夹,文件副本可能需要几秒钟或几分钟才能完成。我已经阅读了有关SO的多个主题(Checking File sizes for changesDetect file in use by other process)。这些都没有给出一个很好的答案。

轮询是“糟糕的”,但我怎么知道文件是否停止增加?具体来说,是否有“文件大小不变”或“文件完整”的通知? OS可以通知非活动(IOW,你如何证明是负面的?)。在我看来,逻辑上,一个人必须轮询一个文件,看看它是否没有改变。我还检查了SCEvents和UKKQueue,但两者都只通知了一个变化。 UKKQueue有一个“文件大小增加”的方法,但没有“文件大小没有增加方法”。

在没有轮询或使用sleep()的情况下,有没有办法检测文件副本完成?

2 个答案:

答案 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);