`
zzbupt
  • 浏览: 86478 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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实现实时监控目录下文件变化的方法

    Java实现实时监控目录下文件变化的方法 Java实现实时监控目录下文件变化的方法是指通过Java语言来实现实时监控目录下文件的变化情况,包括文件的创建、删除、修改等操作。这种方法可以应用于各种场景,例如文件系统...

    乘客打车和司机抢单的Java实现.zip

    在本项目"乘客打车和司机抢单的Java实现.zip"中,...以上是对"乘客打车和司机抢单的Java实现.zip"项目中可能包含的一些核心知识点的详细说明,具体的实现细节还需要参考解压后的代码文件"taxi-master"来进一步分析。

    基于JAVA CS远程监控系统软件的实现(源代码+论文).rar

    通过这个压缩包,学习者不仅可以了解如何用Java实现一个CS架构的远程监控系统,还可以学习到软件开发的完整流程,包括需求分析、设计、编码、测试和文档编写。对于想要深入Java编程或研究远程监控技术的人来说,这是...

    Java-ONVIF 云台控制

    Java-ONVIF 云台控制是针对网络视频监控设备的一种技术实现,主要涉及Java编程语言与ONVIF(Open Network Video Interface Forum)协议的整合。ONVIF是一种国际开放性标准,它定义了IP视频监控设备之间的通信接口,...

    监控文件夹内的文件的变化(Dir Watcher).

    提供的"Demo"很可能是用某种编程语言(如Python、Java、C#等)实现的一个示例程序,用于演示如何使用Dir Watcher库来监控文件夹变化。它可能包括以下部分: 1. 初始化:设置要监控的文件夹路径,并配置感兴趣的事件...

    web项目中定时删除某指定路径下的文件

    综上所述,实现"web项目中定时删除某指定路径下的文件"这一功能,需要结合定时任务框架、文件操作API、路径处理、权限控制、异常处理、日志记录等多个技术点。在实际开发中,应根据具体的技术栈和业务需求来设计和...

    java获取视频信息,帧(封面图片)

    本篇文章将深入探讨如何使用FFmpeg这个强大的跨平台命令行工具,并结合Java进行调用来实现这一功能。FFmpeg是一个开源项目,提供了音频、视频处理的各种功能,包括编码、解码、转换和流处理等。 首先,我们需要在...

    大华以及海康摄像头java的SDK获取预置点集合,设置预置点名称,控制摄像头方向,语音对讲,语音转发,灯光控制最全代码

    通过Java SDK,开发者可以调用相关API获取摄像头支持的所有预置点,这在多场景监控中非常实用。 2. **设置预置点名称**:为了方便记忆和管理,用户可以为每个预置点赋予特定的名称。SDK提供了接口来设定这些名称,...

    Java_某动画游戏的服务器软件重新实现.zip

    在本项目中,我们关注的是"Java_某动画游戏的服务器软件重新实现"。这个话题涉及到使用Java语言来重构或重写一个动画游戏的服务器软件。服务器软件在游戏行业中起着至关重要的作用,它处理玩家的数据交互、游戏状态...

    FastDFS文件服务器Java客户端.zip

    在这个"FastDFS文件服务器Java客户端.zip"压缩包中,包含了FastDFS的Java客户端源码,方便Java开发者在自己的项目中集成FastDFS,实现文件上传和下载等功能。 FastDFS的核心组件包括跟踪服务器(Tracker Server)和...

    利用File类的方法,获得某已有文件的最后修改时间.docx

    在Java编程语言中,获取文件的最后修改时间是一项常见的任务,这对于文件管理和系统监控非常有用。我们可以使用`java.io.File`类提供的方法来实现这一功能。以下是对标题和描述中涉及的知识点的详细说明: ### 文件...

    java实现的网页爬虫1.5版本聚焦爬虫抽取网页

    总之,Java实现的网页爬虫1.5版本聚焦爬虫是一个深入研究和实践Web信息提取的项目。通过合理的设计和优化,它可以有效地从互联网中抽取特定主题的内容,为各种数据分析任务提供数据支持。对于想要学习或提升爬虫技能...

    2014火车票抢票源码java

    综合以上信息,这个Java项目展示了如何利用网络编程、多线程、异步处理等技术来实现一个实时监控和快速响应的火车票抢票系统。同时,它也涉及到了软件工程中的版本控制、项目构建、配置管理等多个方面。对于学习Java...

    基于java实现的可以直接运行的抓包工具,根据域名抓包。超过设置包数量自动启停网络

    标题中的“基于Java实现的可以直接运行的抓包工具”指的是使用Java编程语言开发的一款网络抓包应用程序。这类工具主要用于捕获网络上的数据包,以便分析网络通信情况、检测网络安全问题或者进行网络性能优化。Java是...

    FASTDFS分布式文件系统的使用

    - 配置服务器:设置tracker服务器和storage服务器的配置文件,如`/etc/fdfs`目录下的`tracker.conf`和`storage.conf`。 - 初始化数据:在storage服务器上执行初始化命令,创建必要的目录结构和文件。 - 启动服务:...

    海康威视java开发v5.36.30

    "海康威视java开发v5.36.30"是一个针对海康威视监控设备进行Java开发的软件包,主要服务于开发人员,帮助他们在Java环境中实现对海康威视监控设备的控制和数据交互。 该版本的SDK(Software Development Kit)为CH-...

    机房监控系统(二) 前台部分

    将该文件解压后放入Tomcat的webapps目录,意味着系统前端的Web应用将被Tomcat服务加载并提供给用户访问。 四、系统架构 机房监控系统通常采用B/S(浏览器/服务器)架构,前端通过Web页面与后端服务器进行通信。前端...

    定时监测文件大小

    综上所述,定时监测文件大小是通过定时器实现的一种机制,它能够帮助我们实时监控文件的变化,对于监控系统、数据分析等领域具有重要意义。通过合理的设计和编程,我们可以构建出高效、可靠的文件大小监测系统。

    自动扫描文件夹下文件,加密PDF文件,然后发送邮件

    1. 文件系统监控:为了实现“每隔一秒自动扫描指定的文件夹”,我们需要使用文件系统监控技术。在Java中,我们可以利用`java.nio.file.WatchService` API来监听文件夹的变化。当文件夹内有新PDF文件生成或更新时,...

Global site tag (gtag.js) - Google Analytics