2011-09-20 81 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