记一次本地文件监控功能的实现

项目需求:实时监控ftp服务器中指定目录的文件新增情况,并做统计。
刚接到这个需求,第一反应是直接获取指定File下的所有文件,相隔很短时间再去扫描一次。两次扫描文件一比较,即可知道文件的新增、变化、删除。但本着不重复造轮子的想法,以及为避免很多未预知的错误,在网上一搜,发现有现成的框架,便直接拿来使用(分析源码,大体思路也是如此)。话不多说,直接粘代码。
首先导入maven依赖:

 	<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons-io.version}</version>
 	</dependency>

代码如下:

		String monitorPath ="";
        //扫描间隔
        interval = 1000;
        //interval = Long.valueOf(PropertiesUtils.getPropertie("monitor.local.interval"));
        // 创建过滤器
        //IOFileFilter directories = FileFilterUtils.and(
        //FileFilterUtils.directoryFileFilter(),
        //HiddenFileFilter.VISIBLE);
        //筛选文件后缀
        //IOFileFilter ioFileFilter = FileFilterUtils.suffixFileFilter(".xls");
        IOFileFilter files = FileFilterUtils.and(
        FileFilterUtils.fileFileFilter(),
        FileFilterUtils.suffixFileFilter(""));
        //此处只对文件进行监控
        IOFileFilter filter = FileFilterUtils.or(files);
        //过滤器
        FileAlterationObserver observer = new FileAlterationObserver(new File(monitorPath), filter);
        //不使用过滤器
        //FileAlterationObserver observer = new FileAlterationObserver(new File(rootDir));
        observer.addListener(new FileListener());
        //创建文件变化监听器
        FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer);
        //开始监控(FileAlterationMonitor 实现了runnable)
        monitor.start();

其中FileListener是自定义的类,实现了FileAlterationListenerAdaptor接口。
这个可以自定义文件/目录 create、update、delete时的业务逻辑,具体逻辑自行定义。

public class FileListener extends FileAlterationListenerAdaptor {

    private Logger logger = LoggerFactory.getLogger(FileListener.class);



    /**
     * 文件创建
     */
    @Override
    public void onFileCreate(File file) {
        logger.info("[create]:" + file.getAbsolutePath());
       // FileWorker.exec(file);
    }


    /**
     * 文件修改
     */
    public void onFileChange(File file) {
        logger.info("[onFileChange]:  _"+ file.getAbsolutePath());
    }

    /**
     * 文件删除
     */
    public void onFileDelete(File file) {
        logger.info("[onFileDelete]:" + file.getAbsolutePath());
    }

    /**
     * 目录创建
     */
    public void onDirectoryCreate(File directory) {
        logger.info("[onDirectoryCreate]:" + directory.getAbsolutePath());
    }

    /**
     * 目录修改
     */
    public void onDirectoryChange(File directory) {
    }

    /**
     * 目录删除
     */
    public void onDirectoryDelete(File directory) {
    }

    public void onStart(FileAlterationObserver observer) {
        // TODO Auto-generated method stub
        super.onStart(observer);
    }

    public void onStop(FileAlterationObserver observer) {
        // TODO Auto-generated method stub
        super.onStop(observer);
    }

但此处运行代码发现有几个问题:
1、该扫描是单线程操作的。如果文件监控的业务逻辑处理比较耗时,整个操作会特别耗时间;
2、扫描时文件的大小问题(windows下,文件一旦创建,大小即固定;linux则是文件大小从0开始增长)。这就导致ftp还未完全上传完文件,导致此时文件大小获取错误。
结合项目实际,我创建了无界队列的线程池(没有特别大的文件量)。即每次有新增文件,将File传入线程池去执行,确保ftp文件完整。确保文件完整的逻辑并不复杂,只需多次比较文件的大小、修改时间。
代码不多,如下:

class MyThread extends Thread{

    private File file;
    public MyThread() {
    }

    public MyThread(File file) {
        this.file = file;
    }
    @Override
    public void run() {
        long size = 0;
        long lastModified = 0;
        int count = 0;
        FileInsertService.getInstance().insertFile(file);
        while (file.exists()) {
            // 避免短暂的网络阻塞
            if (size == file.length() && lastModified == file.lastModified()) {
                if (++count >= 2) {
                    break;
                }
            } else {
                size = file.length();
                lastModified = file.lastModified();

            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                return;
            }
        }
        //TODO 自己的业务逻辑
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值