2014-05-07 81 views
1

我需要觀察文件夾 - 文件將放入文件夾中,完成文件複製可能需要幾秒或幾分鐘的時間。我已閱讀過多個主題(Checking File sizes for changesDetect file in use by other process)。這些都不是很好的答案。觀看文件大小更改

輪詢是「壞」,但我怎麼知道文件是否停止增加大小?具體來說,是否有「文件大小恆定」或「文件完整」的通知?操作系統能否通知非活動(IOW,你如何證明是否定的?)。在邏輯上看來,我必須輪詢一個文件,看它是否沒有改變。我也檢查過SCEvents和UKKQueue,但是兩者都只是通知變更。 UKKQueue有一個「文件大小增加」的方法,但沒有「文件大小沒有增加方法」。

真的有任何方法來檢測文件複製完成沒有輪詢或使用睡眠()?

回答

0

如果您可以控制正在傳送的文件,請將它們複製到同一捲上的臨時目錄中,並在完成複製時移動文件。這一舉動只是重新鏈接文件系統中的文件。然後,當文件存在時,kqueue可以通知您。它的存在意味着整個文件在那裏。

順便說一句,當你使用可可文件管理器API的「原子」版本時,這幾乎是它在幕後做的。

如果您沒有控制權,並且只是想監視文件,那麼當文件出現時使用kqueue通知您。隨着文件的增長,隊列會通知您它已被擴展。但是,它不知道是否有其他應用程序擴展文件,因此您仍然需要某種計時器來檢查更改。

我會在我註冊kqueue NOTE_EXTEND事件的同時啓動間隔計時器。我會記錄最後一次看到NOTE_EXTEND事件,並且如果自上次計時器啓動後我沒有看到一個事件,我會認爲文件已停止擴展。

現在,您必須確定要使用什麼計時器值...並且如果您想退出並繼續查找「while」,但除非應用程序通過「移動」複製文件,否則它除外發送一個文件已被完全複製的通知,你將不得不做一些類型的計時器,具有一些任意值...在這個時候你認爲它已經完成。

很明顯,如果你能適應第一種選擇,事情會好得多,因爲你有確定性的方式知道文件已停止增長。

+0

是的,事情是我的應用程序正在觀看網絡文件夾,並且無法控制將顯示哪些文件。 –

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); 
相關問題