Commons-io 文件監控原理

實現原理本質

commons-io實現文件監控的本質就是觀察者模式java

主要的類

  • FileAlterationObserver 觀察者,觀察文件的變化
  • FileAlterationListener 文件變化後的實際操做接口
    • FileAlterationListenerAdaptor FileAlterationListener的實現類
  • FileAlterationMonitor 線程監控,啓動線程定時調用observer方法

代碼實現

FileListener

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...");
    }
}

FileMonitor

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();
        }
    }
}

UML類圖

輸入圖片說明

源碼解析

  1. FileAlterationMonitor的start方法

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) {
            }
        }
    }
  1. FileAlterationObserver的checkAndNotify方法

方法首尾分別調用了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

相關文章
相關標籤/搜索