2011-09-20 75 views
0

我有一个应用程序,监视传入作业的文件夹,然后处理它们。作业由文件夹中包含多个作业文件的文件夹组成。作业通常通过互联网复制,所以当一个文件夹被添加到我的监视文件夹时我让我的应用程序获取作业文件夹内文件的属性,等待20秒,然后比较NSFileSize的当前属性以查看是否存在有任何变化。当一切都匹配,并且没有检测到更改时,它可以传递作业文件夹一起处理。这是我的代码:检查文件大小的变化

while (fileSizes == NO && fileCount == NO) { 
          NSLog(@"going for a loop"); 
          NSArray *jobFiles = [fm subpathsAtPath:jobPath]; 
          NSMutableArray *jobFileAttrs = [[NSMutableArray alloc] init]; 
          int i = 0; 
          while (i < [jobFiles count]) { 
           NSString *filePath = [jobPath stringByAppendingPathComponent:[jobFiles objectAtIndex:i]]; 
           [jobFileAttrs addObject:[fm attributesOfItemAtPath:filePath error:nil]]; 
           ++i;      
          } 
          sleep(20); 
          NSArray *jobFiles2 = [fm subpathsAtPath:jobPath]; 
          NSMutableArray *jobFileAttrs2 = [[NSMutableArray alloc] init]; 
          i = 0; 
          while (i < [jobFiles2 count]) { 
           NSString *filePath = [jobPath stringByAppendingPathComponent:[jobFiles2 objectAtIndex:i]]; 
           [jobFileAttrs2 addObject:[fm attributesOfItemAtPath:filePath error:nil]]; 
           ++i;      
          } 

          if ([jobFiles count] == [jobFiles2 count]) { 
           i = 0; 
           fileSizes = YES; 
           while (i < [jobFiles count]) { 
            NSLog(@"Does %ul = %ul", [[jobFileAttrs objectAtIndex:i] objectForKey:NSFileSize], [[jobFileAttrs2 objectAtIndex:i] objectForKey:NSFileSize]); 
            if ([[jobFileAttrs objectAtIndex:i] objectForKey:NSFileSize] != [[jobFileAttrs2 objectAtIndex:i] objectForKey:NSFileSize]){ 
             fileSizes = NO; 
            } 
            ++i; 
           } 
           if (fileSizes) 
            fileCount = YES; 
          } 

此代码按预期工作Lion中,但是当我在Snow Leopard上运行的应用程序,我得到了NSFileSize属性值不一致。每次循环运行时,我都会得到一个完全不同的值,即使是前一个循环也是如此。很明显,这对于一个文件夹来说已经不再被复制,并且应该给出文件大小的匹配值。

为什么Snow Leopard不能正常工作,我需要做些什么来解决这个问题?我的部分问题是我只在Lion机器上进行开发,所以我必须进行构建,然后使用调试器将其转移到雪豹机器上进行测试。这让我很难排除故障。

回答

4

这有几个问题,但有一件事是,您正在使用布尔运算符(!=)比较两个对象的值。这是比较两个对象的指针位置,而不是它们的值。

比较两个对象,你必须使用isEqual:方法:

if (![[[jobFileAttrs objectAtIndex:i] objectForKey:NSFileSize] isEqual:[[jobFileAttrs2 objectAtIndex:i] objectForKey:NSFileSize]]) 
{ 
    fileSizes = NO; 
} 

其次,这根本就是糟糕的设计。你的代码正在做什么叫做轮询,并且在代码中存在sleep()是一个不好的迹象。你不应该在Cocoa代码中使用sleep,特别是如果你的代码在主线程上执行,因为它会阻塞主运行循环。

如果你绝对必须使用轮询,你应该使用NSTimer对象。

但是,在这种特殊情况下,您不需要使用轮询来确定文件夹内容何时发生变化,您可以使用FSEvents API代替。该API是基于C语言的,有点钝,所以你可能需要使用斯塔·康诺利的SCEvents Objective-C wrapper.

什么,你应该做的是保持目前的文件和它们的文件大小(数组可能含有使用词典的NSArray实例变量文件名和文件属性的关键字),然后当您收到磁盘上的更改通知时,获取文件的当前状态并将其与存储阵列中的信息进行比较。然后,您将用更新的文件信息替换存储的阵列。

其他文件监视选项是kqueues。这些与FSEvents不同,它们是特定于特定文件的,而FSEvents监视目录,而不是单个文件。在你的情况下,kqueues实际上可能更合适。 Uli Kusterer写了一篇很棒的文章Objective-C wrapper for kqueues。如果你使用这个,你只需要开始监控一个特定的文件,并且每当它通过一个委托进行更改时你都会得到通知。如果您只需要一次检查一个文件,这将是一个更简单的选项。

我希望这是有道理的。

+0

感谢您的信息。奇怪的是,比较这两个对象将在狮子工作,但不是雪豹。我实际上使用kqueues作为我的主要手表文件夹。我只恢复到轮询,因为在该文件夹内将添加其他作业文件夹。每个作业文件夹的名称,文件数量,文件大小等都是相当随机的。我不一定需要知道何时对作业文件夹进行了更改,而是什么时候更改已停止(所有文件都从远程计算机传输完成)。我也会研究NSTimer。 – Kris