java实现对某目录下所有文件的监控

转自:http://www.iyouf.info/java-implement-file-monitor.html
在网络上使用java来监控文件状态的文章 例子 太少了。就是有也只是走走过场而已。
今天我特意把这段代码从日志采集系统里面分离出来。供大家参阅,交流,学习。

思路大概是这样的: 通过一个线程 每隔一段时间给某个目录下的文件照个快照 也就是获取这些文件的绝对路径和最后修改的时间,比较前后两次的快照
如果第二次的快照中加入了一个文件,而第一次快照中没有 说明是此文件是新添加的 就触发添加事件,
如果两次的快照中都有这个文件 ,那么就比较次文件前后两次的时间戳,要是不同的话就说明此文件已经改动过了,触发修改事件
第一次的快照中有 而第二次的快照中没有,那么此文件被删掉了,触发文件删除事件

这里的快照我使用一个HashMap来存储当前文件的绝对路径和该文件最后被修改的时间

先定义两个接口 一个是事件的监听器FileLIstener 和文件的触发事件FileEvent
代码里面有相信的注释 这里文字就不写了 ,直接贴代码了

public interface FileListener {

    public void addListener(FileEvent listener);

    public void removeListener(FileEvent listener);

}

public interface FileEvent {
    //添加事件
    public void onAddEvent(Object add);

    //修改事件
    public void onChangeEvent(Object changed);

    //删除事件
    public void onDeleteEvent(Object deleted);
}FileEvent的实现

public class FileEventImpl implements FileEvent {

    protected static final Logger log4j = Logger.getLogger(FileEventImpl.class);

    public FileEventImpl() {
        super();
    }

    /**
     * 文件被添加时触发的事件
     */
    public void onAddEvent(Object add) {
        if (add instanceof File) {
            File file = (File) add;
            if (file.isFile()) {
               log4j.info(fileAbsolutePath + " is added!");
            }
        }
    }

    /**
     * 文件修改时的触发事件
     */
    public void onChangeEvent(Object changed) {
        if (changed instanceof File) {
            File file = (File) changed;
            if (file.isFile()) {
                String fileAbsolutePath = file.getAbsolutePath();
                log4j.info(fileAbsolutePath + " is changed");
            }
        }
    }

    public void onDeleteEvent(Object deleted) {
        if (deleted instanceof String) {
            String deletedFile = (String) deleted;
            log4j.info(deletedFile + " is deleted");
        }
    }
}不停的监控线程

public abstract class IntervalThread implements Runnable {

    //线程的状态
    private boolean active = false;

    //线程睡眠的时间
    private int interval = -1;

    private Thread runner;

    public IntervalThread(int intervalSeconds) {
        this.interval = intervalSeconds * 1000;
    }

   /**
    * 线程启动
    */
    public void start() {
        active = true;
        if (runner == null && interval > 0) {
            runner = new Thread(this);
            runner.start();
        }
    }

    public void stop() {
        active = false;
    }

    public void run() {

        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        while (active) {
            try {
                doInterval();
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    protected abstract void doInterval();
}

public abstract class AbstractResourceWatcher extends IntervalThread implements
        FileListener {

    private List<FileEvent> listeners = new LinkedList<FileEvent>();

    public AbstractResourceWatcher(int intervalSeconds) {
        super(intervalSeconds);
    }

    //清空绑定监听器
    public void removeAllListeners() {
        listeners.clear();
    }

    public void addListener(FileEvent listener) {
        listeners.add(listener);
    }

    public void removeListener(FileEvent listener) {
        listeners.remove(listener);
    }

    /**
     * 当一个资源被添加到这,此方法将被调用. 它会触发onAdd()方法
     */
    protected void resourceAdded(Object add) {

        for (Iterator<FileEvent> it = listeners.iterator(); it
                .hasNext();) {
            it.next().onAddEvent(add);
        }
    }

    /**
     * 当一个文件被改变的时候 它会触发onChange方法
     *
     * @param changedResource
     */
    protected void resourceChanged(Object changed) {
        for (Iterator<FileEvent> it = listeners.iterator(); it
                .hasNext();) {
            it.next().onChangeEvent(changed);
        }
    }

    /**
     * 一个文件被删除时的触发事件
     * @param deleted
     */
    protected void resourceDeleted(Object deleted) {
        for (Iterator<FileEvent> it = listeners.iterator(); it
                .hasNext();) {
            it.next().onDeleteEvent(deleted);
        }
    }

    protected abstract void doInterval();
}最后 这个类就是最关键的了

/**
* 这个类 主要是监控 目录中文件的变化情况
* @author dengm
*
*/
public class DirectoryWatcher extends AbstractResourceWatcher {

    protected static final Logger log4j = Logger.getLogger(DirectoryWatcher.class);

    //当前文件的快照
    private Map<String,Long> currentFiles = new HashMap<String,Long>();

    //上一次文件的快照
    private Map<String,Long> prevFiles = new HashMap<String,Long>();

    private String directory;

    public DirectoryWatcher(String directoryPath, int seconds)
            throws RuntimeException {

        //线程运行的时间间隔
        super(seconds);

        File logDirectory = new File(directoryPath);

        //检查当前的日志目录是否存在
        if (logDirectory != null && !logDirectory.isDirectory()) {
            //不存在的话就给他创建一个
            logDirectory.mkdir();
        }
        this.directory = directoryPath;
        log4j.info("Start to monitor " +this.directory);
    }

    public void start() {
        //记录当前文件的时间戳
        takeSnapshot();

        //启动线程
        super.start();
    }

    //让线程停止工作  ....暂时还没用上
    public void stop() {
        super.stop();
    }

    /**
     * 存储文件名和最后修改的所有文件
     */
    private void takeSnapshot() {

        //清空上一次的快照,把当前的快照设置为上次的
        prevFiles.clear();
        prevFiles.putAll(currentFiles);

        //清空当前的快照信息
        currentFiles.clear();

        File dir = new File(directory);
        iteratorDirectory(dir);
    }

    private void iteratorDirectory(File directory){
         File[] files = directory.listFiles();
        //保存当前文件和最后修改的时间戳
         for(File file: files){
             //如果是目录 递归
             if(file.isDirectory()){
                 iteratorDirectory(file);
             }else{
                 currentFiles.put(file.getAbsolutePath(),
                     new Long(file.lastModified()));
             }
         }
    }

    private void checkFileStatus(String fileName,Long lastModified){
         //如果没有这个文件名,说明是刚刚添加的
        if (!prevFiles.containsKey(fileName)) {
            resourceAdded(new File(fileName));

        }else if (prevFiles.containsKey(fileName)) {
            //包含这个文件,然后前后的时间比较一下
            Long prevModified = (Long) prevFiles.get(fileName);

            //如果时间不等说明被修改了
            if (prevModified.compareTo(lastModified) != 0) {
                    resourceChanged(new File(fileName));
            }
        }
    }

    private void checkFile(){
         Set<Entry<String,Long>> set = currentFiles.entrySet();

         //遍历当前的文件列表
         Iterator<Entry<String, Long>> currentIt = set.iterator();

         while (currentIt.hasNext()) {
             Map.Entry<String, Long> entry = currentIt.next();
             String fileName = entry.getKey();
             Long lastModified = entry.getValue();
             File file = new File(fileName);
             //又是递归..
             if(file.isDirectory()){
                 File files[] = file.listFiles();
                 for(File f: files){
                     checkFileStatus(f.getAbsolutePath(),lastModified);
                 }
             }else{
                 checkFileStatus(fileName,lastModified);
             }
         }

         Set<Entry<String,Long>> preSet = prevFiles.entrySet();
         Iterator<Entry<String, Long>> prevIt = preSet.iterator();

         while (prevIt.hasNext()) {
             Map.Entry<String, Long> entry = prevIt.next();
             String fileName = entry.getKey();
             //文件被删了.
             if (!currentFiles.containsKey(fileName)) {
                 resourceDeleted(fileName);
             }
         }
    }

    /**
     * 检查目录中的任何变化
     */
    protected void doInterval() {

        //又照个快照
        takeSnapshot();
        //当前的快照和上次的快照对比 就是比较两次的时间戳
        checkFile();
    }
}测试代码
public static void main(String[] args) {
        DirectoryWatcher dw = new DirectoryWatcher("/opt/raphael", 5);
        //添加一个文件监听
        dw.addListener(new FileEventImpl());
        dw.start();
    }

你可能感兴趣的:(java,thread,log4j,F#)