文件监控利器-Jnotify

监听的文件变化的方式有很多,但是比较完美的还是jNotify
https://jnotify.sourceforge.net/
对比一下监控方式的优缺点

方式 缺点
java原生watch 可能对文件时间获取有缺毫秒的问题
commons-io 没有文件重命名事件的监听实现
jNotify 配置复杂,需要添加dll/so文件到系统

具体的jnotfiy的配置可自行查找。

现在给出jnotify的具体实现

  1. 导入依赖
<!-- https://mvnrepository.com/artifact/net.contentobjects.jnotify/jnotify -->
<dependency>
    <groupId>net.contentobjects.jnotify</groupId>
    <artifactId>jnotify</artifactId>
    <version>0.94</version>
</dependency>
  1. 编写监控代码

import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyAdapter;
import net.contentobjects.jnotify.JNotifyException;

import java.io.File;

public class Watch extends JNotifyAdapter {

    //可以写到配置文件中
    private static String WATCH_BASE_PATH;
    public Watch(String path){
        Watch.WATCH_BASE_PATH = path;
    }
    /**
     * 关注目录的事件
     */
    int mask =JNotify.FILE_CREATED |JNotify.FILE_DELETED| JNotify.FILE_RENAMED| JNotify.FILE_MODIFIED;
    /**
     * 是否监视子目录,即级联监视
     */
    boolean watchSubtree = true;
    /**
     * 监听程序Id
     */
    public int watchID;

    /**
     * 容器启动时启动监视程序
     */
    public void beginWatch() {
        /**
         * 添加到监视队列中
         */
        try {
            this.watchID = JNotify.addWatch(WATCH_BASE_PATH, mask, watchSubtree, this);
            System.err.println("jnotify -----------启动成功-----------:" + watchID );
        } catch (JNotifyException e) {
            e.printStackTrace();
        }
        /**
         * 死循环,线程一直执行,休眠一分钟后继续执行,主要是为了让主线程一直执行 休眠时间和监测文件发生的效率无
         * (就是说不是监视目录文件改变一分钟后才监测到,监测几乎是实时的,调用本地系统库)
         */
        while (true) {
            try {
                //主要缓和主线程的执行效率,
                Thread.sleep(600);
            } catch (InterruptedException e) {
                // ignore it
            }
        }
    }

    /**
     * 文件创建
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param name 文件名
     */

    @Override
    public void fileCreated(int wd, String rootPath, String name) {

        System.err.println(wd+"----->文件被创建, 创建位置为: " + rootPath + "\\" + name);
    }

    /**
     * 删除文件
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param name 文件名
     */
    @Override
    public void fileDeleted(int wd, String rootPath, String name) {
        System.err.println(wd+"----->文件被删除, 被删除的文件名为:" + rootPath + name);
    }

    /**
     * 文件修改 (文件内容被修改和文件夹被修改都可以检测到)
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param name 文件名
     */
    @Override
    public void fileModified(int wd, String rootPath, String name) {
        String filePath = rootPath + name;
        boolean isDir = filePath.indexOf('.') < 1;
        // 是目录变更
        if(filePath.indexOf('.') < 1){
            return;
        }
        System.err.println(wd+"----->文件内容被修改, 文件名为:" + rootPath + "\\" + name + ", isdir:" + isDir);
    }

    /**
     * 文件重命名
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param oldName 修改前目录名
     * @param newName 修改后目录名
     */
    @Override
    public void fileRenamed(int wd, String rootPath, String oldName, String newName) {
        String filePath = rootPath + oldName;
        // 是目录变更
        if(filePath.indexOf('.') < 1){
            System.err.println(wd+"----->文件夹被重命名, 原文件名为:" + rootPath + "\\" + oldName
                    + ", 现文件名为:" + rootPath + "\\" + newName);

        } else {
            System.err.println(wd+"----->文件被重命名, 原文件名为:" + rootPath + "\\" + oldName
                    + ", 现文件名为:" + rootPath + "\\" + newName);

        }
    }
}
  1. 查看输出
    image
posted @   原子切割员  阅读(565)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
点击右上角即可分享
微信分享提示