2013-07-29 64 views
17

我正在使用WatchService API觀看目錄,並在用戶開始將文件複製到目錄時獲取ENTRY_CREATE事件。儘管我正在使用的文件可能很大,並且我想知道副本何時完成。是否有任何內置的Java API可用於實現此目標,或者我最好只跟蹤創建的文件的大小,並在大小停止增長時開始處理?如何判斷文件何時「完成」複製到監視目錄中?

編輯:這裏是我的示例代碼:

package com.example; 

import java.io.File; 
import java.nio.file.FileSystems; 
import java.nio.file.Path; 
import java.nio.file.StandardWatchEventKinds; 
import java.nio.file.WatchEvent; 
import java.nio.file.WatchKey; 
import java.nio.file.WatchService; 

public class Monitor { 
    public static void main(String[] args) { 
     try { 
      String path = args[0]; 

      System.out.println(String.format("Monitoring %s", path )); 
      WatchService watcher = FileSystems.getDefault().newWatchService(); 
      Path watchPath = FileSystems.getDefault().getPath(path); 

      watchPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY); 

      while (true) { 
       WatchKey key = watcher.take(); 
       for (WatchEvent<?> event: key.pollEvents()) { 
        Object context = event.context(); 
        System.out.println(String.format("Event %s, type %s", context, event.kind())); 

       } 
      } 

     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

產生這樣的輸出:

Monitoring /Users/ericcobb/Develop/watch 
Event .DS_Store, type ENTRY_MODIFY 
Event 7795dab5-71b1-4b78-952f-7e15a2f39801-84f3e5daeca9435aa886fbebf7f8bd61_4.mp4, type ENTRY_CREATE 

回答

8

當創建一個條目,你會得到一個ENTRY_CREATE事件。對於後續的每一項修改,您都會收到ENTRY_MODIFY事件。複製完成後,您將收到一個ENTRY_MODIFY的通知。

+0

有趣的是,這實際上是我所預期的/期望的行爲,但不是我所看到的。我添加了一些代碼和示例輸出,你看到什麼東西出來嗎? – eric

+0

@eric也許它正在與創建滾動修改? – Jeffrey

+0

@傑弗裏這很清楚。問題是如何發現這是最後一次ENTRY_MODIFY,因爲我得到了它們中的幾個(centos)。你可以解釋嗎? – 2014-05-01 17:25:16

2
  • 我認爲最常見的方法是將文件複製到同一分區的臨時目錄中,然後通過原子移動命令將其移動到受監視的目錄中。
  • 也許一個解決方案也可以通過與文件時間戳

但是這兩種解決方案需要在書面申請,以實現玩弄實現。我認爲你無法從閱讀應用程序中確定地告訴你。

+0

這不僅是最常見的,也是唯一一條可以完成修改的簡單方法。 –

+0

如果文件的大小像n GB一樣會怎樣。此解決方案是否可以工作,或者我們將檢查EOF,直到文件被下載? – Dhairyashil

0

也許你可以嘗試獲取該文件的寫權限告訴,但是這取決於兩個因素,需要研究:

  1. 的書面申請必須獲得獨佔寫權限的文件,並不得靠近它之前的文件實際上是完整的。
  2. 它必須可以從Java進行測試。我試試看opening the file as FileChannel是否爲WRITE訪問會引發異常,如果該文件仍被其他程序寫入時被鎖定。不幸的是,Javadoc沒有詳細說明這一點。
2

這是庫是我們今天使用:

https://github.com/levelsbeyond/jpoller

它是一個開源項目,原作者不再維護的一個分支。我們已經修復了一些錯誤,並且今天在生產中使用它。

它通過檢查目錄中文件的大小來工作,並在文件大小停止增長一段時間後認爲文件已完成(可以處理)。

0
File file = child.toAbsolutePath().toFile(); 
if(file.isFile() && file.isWrite()) 
{ 
} 

也許這將是找出你想要的,但不是在while語句中的方式。

它會工作時,你真的訪問文件。

0

唯一有效的選擇是確保沒有其他進程正在寫入文件,而是成功獲取文件上的寫入鎖定。雖然有點笨拙,你可以使用FileChannelFileLock爲此

try(FileChannel ch = FileChannel.open(p, StandardOpenOption.WRITE); 
    FileLock lock = ch.tryLock()){ 

    if(lock == null) { 
     //no lock, other process is still writing    
    } else { 
     //you got a lock, other process is done writing 
    } 
} catch (IOException e) { 
    //something else went wrong 
} 

你還可獲得使用ch.lock()這是一個阻塞調用的鎖。但是由於ENTRY_MODIFY事件在寫入文件時不斷產生,所以您可以使用tryLock並等待下一個事件。

相關問題