Java中实时监控目录下文件变化的两种实现方法,一中是基于jdk7之后,java自带的文件监控工具(Watch Service),一种是使用Commons-io的monitor下的相关类可以处理对文件进行监控。

1. 基于WatchService实现文件监控

Java 7的新IO - NIO.2提供了一组新的类和方法,主要存在于java.nio包内。它完全取代了java.io.File与文件系统的交互,并提供了新的异步处理类,无需手动配置线程池和其他底层并发控制,便可在后台线程中执行文件和网络IO操作。

Watch Service API可用于将指定目录注册到监视服务上。注册时须指定事件类型,如文件创建,修改,删除等。相关类图如下:

WatchService是监视服务接口,在不同系统上有不同的实现类。实现了Watchable接口的对象方可注册监视服务,java.nio.file.Path实现了此接口。WatchKey表示Watchable对象和WatchService的关联关系,在注册时被创建。注册完成后,WatchKey将被置为'ready'状态,直到下列三种情况之一发生:

  1. WatchKey.cancel()被调用
  2. 被监控的目录不存在或不可访问
  3. WatchService对象被关闭

当文件改动发生时,WatchKey的状态将会被置为"signaled"然后被放入待处理队列中。WatchService提供了三种从队列中获取WatchKeys的方式:

  1. poll - 返回队列中的一个key。如果没有可用的key,将立即返回null。

  2. poll(long, TimeUnit) - 如果队列中存在可用的key则将之返回,否则在参数预置的时间内等待可用的key。TimeUnit用来指定前一个参数表示的时间是纳秒、毫秒或是其他的时间单位。
    例子:final WatchKey watchKey = watchService.poll(1, TimeUnit.MINUTES);将会等待1分钟

  3. take - 方法将会等待直到可用的key被返回。
    示例如下:


/** * Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements.  See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with* the License.  You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.**/
package com.tompai.file;import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** @desc: demo* @name: FileWatchTask.java* @author: tompai* @email:liinux@qq.com* @createTime: 2020年1月7日 下午12:55:46* @history:* @version: v1.0*/public class FileWatchTask implements Runnable{public String fileDirectory;public static final Logger logger = LoggerFactory.getLogger(FileWatchTask.class);public FileWatchTask(String fileDirectory) {this.fileDirectory = fileDirectory;}ExecutorService cachedThreadPool = Executors.newFixedThreadPool(5);public void run() {WatchService service = null;try {// 获取当前文件系统的监控对象service = FileSystems.getDefault().newWatchService();} catch (Exception e) {e.printStackTrace();}try {// 获取文件目录下的Path对象注册到 watchService中。// 监听的事件类型,有创建,删除,以及修改Paths.get(fileDirectory).register(service, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);} catch (IOException e) {e.printStackTrace();}while (true) {WatchKey key = null;try {// 获取可用key.没有可用的就waitkey = service.take();} catch (InterruptedException e) {e.printStackTrace();}for (WatchEvent<?> event : key.pollEvents()) {// todologger.info(event.context() + "文件:" + event.kind() + "次数: " + event.count());}// 重置,这一步很重要,否则当前的key就不再会获取将来发生的事件boolean valid = key.reset();// 失效状态,退出监听if (!valid) {break;}}}
}

然后创建一个线程开始进行监听:


/** * Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements.  See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to You under the Apache License, Version 2.0* (the "License"); you may not use this file except in compliance with* the License.  You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.**/
package com.tompai.file;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/**
* @desc: demo
* @name: MyWatchService.java
* @author: tompai
* @email:liinux@qq.com
* @createTime: 2020年1月7日 下午12:57:29
* @history:
* @version: v1.0
*/public class MyWatchService {/*** @author: tompai* @createTime: 2020年1月7日 下午12:57:29* @history:* @param args void*/public static void main(String[] args) {//TODO Auto-generated method stub//要监控的文件目录String propFileName = "F:/test";//因为是线程安全的所以可以放入ThreadPool中使用ExecutorService cachedThreadPool = Executors.newFixedThreadPool(1);cachedThreadPool.execute(new FileWatchTask(propFileName));}}

2. 利用common-io包进行监控

使用Commons-io的monitor下的相关类可以处理对文件进行监控,它采用的是观察者模式来实现的

  • 可以监控文件夹的创建、删除和修改
  • 可以监控文件的创建、删除和修改
  • 采用的是观察者模式来实现的
  • 采用线程去定时去刷新检测文件的变化情况

2.1 导入依赖

<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>

2.2 编写FileListener类

/*** 文件变化监听器** 在Apache的Commons-IO中有关于文件的监控功能的代码. 文件监控的原理如下:* 由文件监控类FileAlterationMonitor中的线程不停的扫描文件观察器FileAlterationObserver,* 如果有文件的变化,则根据相关的文件比较器,判断文件时新增,还是删除,还是更改。(默认为1000毫秒执行一次扫描)***/
public class FileListener extends FileAlterationListenerAdaptor {private Logger log = Logger.getLogger(FileListener.class);/*** 文件创建执行*/public void onFileCreate(File file) {log.info("[新建]:" + file.getAbsolutePath());}/*** 文件创建修改*/public void onFileChange(File file) {log.info("[修改]:" + file.getAbsolutePath());}/*** 文件删除*/public void onFileDelete(File file) {log.info("[删除]:" + file.getAbsolutePath());}/*** 目录创建*/public void onDirectoryCreate(File directory) {log.info("[新建]:" + directory.getAbsolutePath());}/*** 目录修改*/public void onDirectoryChange(File directory) {log.info("[修改]:" + directory.getAbsolutePath());}/*** 目录删除*/public void onDirectoryDelete(File directory) {log.info("[删除]:" + directory.getAbsolutePath());}public void onStart(FileAlterationObserver observer) {// TODO Auto-generated method stubsuper.onStart(observer);}public void onStop(FileAlterationObserver observer) {// TODO Auto-generated method stubsuper.onStop(observer);}}

2.3 编写测试方法

public static void main(String[] args) throws Exception{// 监控目录String rootDir = "F:/test";// 轮询间隔 3 秒long interval = TimeUnit.SECONDS.toMillis(3);// 创建过滤器IOFileFilter directories = FileFilterUtils.and(FileFilterUtils.directoryFileFilter(),HiddenFileFilter.VISIBLE);IOFileFilter files = FileFilterUtils.and(FileFilterUtils.fileFileFilter(),FileFilterUtils.suffixFileFilter(".txt"));IOFileFilter filter = FileFilterUtils.or(directories, files);// 使用过滤器FileAlterationObserver observer = new FileAlterationObserver(new File(rootDir), filter);//不使用过滤器//FileAlterationObserver observer = new FileAlterationObserver(new File(rootDir));observer.addListener(new FileListener());//创建文件变化监听器FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer);// 开始监控monitor.start();}

3. 两者的区别

相比于jdk自带的文件监控,common-io有以下优点

  • 可以对其子文件夹进行监控,只能提示目录被修改。
  • 可以对文件类型进行过滤。
    另外:当使用WatchService时,文件修改时,会被调用两次,输出两个相同的修改。

Java中实时监控目录下文件变化的两种实现方法介绍相关推荐

  1. C#实现实时监控文件目录下的变化

    本文主要描述如何通过C#实现实时监控文件目录下的变化,包括文件和目录的添加,删除,修改和重命名等操作. 首先,我们需要对.net提供的FileSystemWatcher类有所了解.我有些懒,找了MSD ...

  2. Python监控目录和文件变化

    原文:https://www.cnblogs.com/lcamry/p/8392376.html Python监控目录和文件变化 一.os.listdir import os, time path_t ...

  3. java整型转换为数组_基于java中byte数组与int类型的转换(两种方法)

    java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形 ...

  4. win8 java不是内部或外部命令_win8系统运行java提示“ava不是内部或外部命令两种解决方法...

    Java一种可以撰写跨平台应用软件的面向对象的程序设计语言,最近有一些小伙伴使用win10操作系统的时候遇到了一个问题,win8系统win8系统运行java突然提示"java不是内部或外部命 ...

  5. java 计时 timeclock_计时器的time_t和clock_t 的两种实现方法(推荐)

    想给自己初步完成的相空间搜索算法计算一下运行时间,于是尝试了如下使用 time_t 类型的方式 #include #include #include #include "StateFunct ...

  6. 在windows下实时监控、接受文件变化小工具

    在windows下实时监控文件变化小工具 在测试的时候,我们可能想实时监控系统打出的log信息,在unix系统上我们可以用"tail -f"实现,在windows下一般就无法做到实 ...

  7. Java中读取某个目录下的所有文件和文件夹

    import java.io.File; public class Test1 {public static void main(String[] args) {String path="d ...

  8. FileAlterationMonitor监听目录下文件变化

    工具类 FileMonitor package com.ncs.wavtrans.utils;import org.apache.commons.io.monitor.FileAlterationLi ...

  9. C#中删除目录以及目录下文件的方法

    场景 C#中根据文件夹路径,将文件夹以及文件夹下文件删除. 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关 ...

  10. 【JAVA】删除指定目录下文件、文件夹

    今天遇到一个删除指定目录下的文件和文件夹的功能,直接上代码吧! import java.io.File;/*** @version 2019/4/12 9:35* @description Test* ...

最新文章

  1. vs2012下编码引起的一个神坑
  2. 自动驾驶进入第3阶段 ADAS黑科技守护开车人
  3. 安装SeleniumPhantomJS
  4. C/Cpp / 构造函数种类
  5. linux2.6驱动学习笔记之字符驱动
  6. 《Python Cookbook 3rd》笔记(5.4):读写字节数据
  7. 注解 @CrossOrigin
  8. java线程中Exchanger使用
  9. asp小偷转html,ASP中实现小偷程序的原理和简单示例
  10. 大学生期末网页制作代码以及网页设计排版技巧
  11. 基于单片机的光立方设计
  12. 页面跳转 并将改页面从历史栈中删除
  13. 我的专业我的梦作文计算机,我的创新我的梦优秀作文
  14. php写前端还是nodejs,javascript - 新手想在短期内写一个个人博客,是用php还是用nodejs?...
  15. 宏观低速物理 '牛顿篇'
  16. L1-039 古风排版 (20分)
  17. 用计算机丧失了大脑,《心理科》您真的需要大脑“升级”吗? 将大脑视为计算机是有缺...
  18. 漫谈云数据中心的前世今生
  19. 【云原生】Kubernetes PDB(Pod Disruption Budget)介绍与简单使用
  20. c++程序设计练习2.1

热门文章

  1. 11. Window open() 方法
  2. linux input设备冲突,linux input设备怎么固定event handler
  3. HP推出UFT新版本UFT12 5以及LeanFT
  4. msysgit+apache安装说明 - gitweb服务器部分
  5. RabbitMQ实战:理解消息通信
  6. 网络安全态势感知(NSSA)----引言
  7. Python:generator的send()方法流程分析
  8. CentOS7安装GNOME可视化界面
  9. iOS开发中设置UITextField的占位文字的颜色,和光标的颜色
  10. date,datetime,timestamp 的区别