commons-io實現文件監控的本質就是觀察者模式java
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import org.apache.commons.io.monitor.FileAlterationObserver; import java.io.File; public class FileListener extends FileAlterationListenerAdaptor { @Override public void onStart(FileAlterationObserver observer) { System.out.println("start..."); } @Override public void onFileCreate(File file) { System.out.println(file.getName() + "file create..."); } @Override public void onFileChange(File file) { System.out.println(file.getName() + "file change..."); } @Override public void onFileDelete(File file) { System.out.println(file.getName() + "file delete..."); } @Override public void onStop(FileAlterationObserver observer) { System.out.println("stop..."); } }
import org.apache.commons.io.monitor.FileAlterationMonitor; import org.apache.commons.io.monitor.FileAlterationObserver; public class FileMonitor { public static void main(String[] args) { FileAlterationObserver observer = new FileAlterationObserver("F:/test"); observer.addListener(new FileListener()); FileAlterationMonitor monitor = new FileAlterationMonitor(30000, observer); try { monitor.start(); } catch (Exception e) { e.printStackTrace(); } } }
observer的初始化工做,啓動線程,線程啓動後,用一個while循環不停的調用每一個observer的checkAndNotify方法c++
public synchronized void start() throws Exception { if (running) { throw new IllegalStateException("Monitor is already running"); } for (FileAlterationObserver observer : observers) { observer.initialize(); } running = true; if (threadFactory != null) { thread = threadFactory.newThread(this); } else { thread = new Thread(this); } thread.start(); } public void run() { while (running) { for (FileAlterationObserver observer : observers) { observer.checkAndNotify(); } if (!running) { break; } try { Thread.sleep(interval); } catch (final InterruptedException ignored) { } } }
方法首尾分別調用了FileAlterationListener的onStart()和onStop()方法,中間調用私有的checkAndNotify方法,其中遞歸檢查文件及目錄,並執行doCreate、doMatch、doDelete方法,這3個方法內部仍是調用FileAlterationListener的方法apache
public void checkAndNotify() { /* fire onStart() */ for (FileAlterationListener listener : listeners) { listener.onStart(this); } /* fire directory/file events */ File rootFile = rootEntry.getFile(); if (rootFile.exists()) { checkAndNotify(rootEntry, rootEntry.getChildren(), listFiles(rootFile)); } else if (rootEntry.isExists()) { checkAndNotify(rootEntry, rootEntry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); } else { // Didn't exist and still doesn't } /* fire onStop() */ for (FileAlterationListener listener : listeners) { listener.onStop(this); } } private void checkAndNotify(FileEntry parent, FileEntry[] previous, File[] files) { int c = 0; FileEntry[] current = files.length > 0 ? new FileEntry[files.length] : FileEntry.EMPTY_ENTRIES; for (FileEntry entry : previous) { while (c < files.length && comparator.compare(entry.getFile(), files[c]) > 0) { current[c] = createFileEntry(parent, files[c]); doCreate(current[c]); c++; } if (c < files.length && comparator.compare(entry.getFile(), files[c]) == 0) { doMatch(entry, files[c]); checkAndNotify(entry, entry.getChildren(), listFiles(files[c])); current[c] = entry; c++; } else { checkAndNotify(entry, entry.getChildren(), FileUtils.EMPTY_FILE_ARRAY); doDelete(entry); } } for (; c < files.length; c++) { current[c] = createFileEntry(parent, files[c]); doCreate(current[c]); } parent.setChildren(current); }
我的以爲FileAlterationObserver是被觀察者,FileAlterationListener是觀察者,前者檢測文件是否有變化,當文件有變化時通知後者作相應實現。ide