kQueue目录监控

时间:2013-03-08 03:01:11

标签: ios c kqueue

我的应用程序的Documents目录中有一个kQueue观察者。我正在使用当Documents目录内容发生变化时触发回调的kQueue。

这里有两个设置

eventToAdd.flags  = EV_ADD | EV_CLEAR;
eventToAdd.fflags = NOTE_WRITE;

问题是当添加新文件时内容发生变化时我收到通知,但实际文件尚未完全复制,因此当我尝试处理新文件时,我收到SIGABRT崩溃。

如何在文件完成之前延迟通知?

2 个答案:

答案 0 :(得分:2)

我通过创建2个侦听器来解决这个问题...一个在应用程序的Documents目录中,用于监视出现的新文件,以及为每个出现的文件创建的File代理对象。 File对象具有fileBusy标志。当一块数据写入文件时,File对象设置一个2秒的计时器。我假设如果在计时器到期之前没有更新,则完全写入文件。

文件更改侦听器代码:https://gist.github.com/nielsbot/5155671

以下听众的我(部分)代表。 (表示磁盘上文件的“File”对象)

@implementation File<FileChangeObserverDelegate>

    -(void)scheduleFileBusyTimeout
    {
        self.fileBusyTimeoutTimer = [ NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector( fileBusyTimeoutTimerFired: ) userInfo:nil repeats:NO ] ;
    }

    -(void)setFileChangeObserver:(FileChangeObserver *)observer
    {
        [_fileChangeObserver invalidate ] ;
        _fileChangeObserver = observer ;
    }

    -(void)fileChanged:(FileChangeObserver *)asset typeMask:(enum FileChangeNotificationType)type
    {
        @synchronized( self )
        {
            if ( ( type & kFileChangeType_Delete ) != 0 )
            {
                // we're going away soon...
                self.fileChangeObserver = nil ;
            }
            else
            {

                self.fileBusy = YES ;
                [ self scheduleFileBusyTimeout ] ;
            }
        }
    }

    -(void)fileBusyTimeoutTimerFired:(NSTimer*)timer
    {
        @autoreleasepool {
            self.fileBusy = NO ;
        }
    }

    -(void)setFileBusyTimeoutTimer:(NSTimer *)timer
    {
        [ _fileBusyTimeoutTimer invalidate ] ;
        _fileBusyTimeoutTimer = timer ;
    }
@end

答案 1 :(得分:0)

首先,请参阅:

简短的回答是没有好办法做到这一点。理想情况下,您应该将文件写入其他位置,然后将其移动到Documents中。这使它成为原子动作。或者将其写为特殊文件名(“。partial”,“。download”等)并在结尾处重命名(同样,将触发第二个kqueue事件的原子动作)。