Java 7之前的版本都是沒有原生支援的,下面就說說JDK 1.7 以下版本平台的解決方案:
事件驅動方式,無需無目錄掃描,但與平台相關
線程輪詢掃描,純java實現,完美跨平台,但監聽檔案較多時,掃描的量太大,響應不是非常及時,依賴於掃描間隔時間
JNotify屬於事件驅動,所以不同的平台的處理方式不一樣。所以需要在java.library.path裡面添加jnotify.dll/jnotify_64bit.dll,最簡單的解決方案直接修改代碼。JNotify_win32.java的47和51行的System.loadLibrary改為System.load(dllpath),其他平台的修改也是一樣的。然後把dll,so檔案導成jar包,世界就清靜了。
使用非常簡單,範例程式碼如下
| 代碼如下 |
複製代碼 |
public static void main(String[] args) throws InterruptedException, IOException { String dir = new File(args.length == 0 ? "." : args[0]).getCanonicalFile().getAbsolutePath(); JNotify.addWatch(dir, FILE_ANY, true, new JNotifyListener() { public void fileRenamed(int wd, String rootPath, String oldName, String newName) { System.out.println("renamed " + rootPath + " : " + oldName + " -> " + newName); } public void fileModified(int wd, String rootPath, String name) { System.out.println("modified " + rootPath + " : " + name); } public void fileDeleted(int wd, String rootPath, String name) { System.out.println("deleted " + rootPath + " : " + name); } public void fileCreated(int wd, String rootPath, String name) { System.out.println("created " + rootPath + " : " + name); } }); System.err.println("Monitoring " + dir + ", ctrl+c to stop"); while (true) Thread.sleep(10000); } |
Jpathwath要寫的代碼稍微多點。事件說明參考這個,簡單樣本如下
| 代碼如下 |
複製代碼 |
public static void main(String[] args) { WatchService watchService = FileSystems.getDefault().newWatchService(); Path watchedPath = Paths.get("E:/temp"); try { WatchKey key = watchedPath.register(watchService, StandardWatchEventKind.ENTRY_MODIFY); System.out.println(key.isValid()); } catch (UnsupportedOperationException uox) { System.err.println("file watching not supported!"); } catch (IOException iox) { System.err.println("I/O errors"); } for (;;) { // take() will block until a file has been created/deleted WatchKey signalledKey; try { signalledKey = watchService.take(); } catch (InterruptedException ix) { continue; } catch (ClosedWatchServiceException cwse) { System.out.println("watch service closed, terminating."); break; } List<WatchEvent<?>> list = signalledKey.pollEvents(); signalledKey.reset(); for (WatchEvent<?> e : list) { String message = ""; if (e.kind() == StandardWatchEventKind.ENTRY_MODIFY) { Path context = (Path) e.context(); message = context.toString() + " modified"; } System.out.println(message); } } } |
需要注意的是Windows平台下,重新命名一個檔案,產生2個事件——重新命名和修改,在事件處理的時候需要注意。