两种监控文件和目录方式
Commons-io
- 在Apache的Commons-io提供文件的监控功能。
- 由文件监控类FileAlterationMonitor中的线程不停的扫描文件观察器FileAlterationObserver。
- 如果有文件的变化,则根据相关的文件比较器,判断文件时新增,还是删除,还是更改。(默认为1000毫秒执行一次扫描)
WatchService
- Java1.7中提供了NIO WatchService来监控系统中文件的变化。
- 该监控是基于操作系统的文件系统监控器,可以监控系统是所有文件的变化,这种监控是无需遍历、无需比较的,是一种基于信号收发的监控。
整个监控目录文件操作的流程大致如下:
- 获取 WatchService
- 注册指定目录的监视器
- 等待目录下的文件发生变化
- 对发生变化的文件进行操作
WatchService文件监控
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
834j
public class FileWatchTask implements Runnable {
private String fileDirectory;
private List<String> monitorFileNameList = new ArrayList<>();
private ParseIF parseIF;
/**
* @param fileDirectory 监控目录
* @param monitorFileNameList 监控文件名
* @param parseIF 处理函数
*/
public FileWatchTask(String fileDirectory, List<String> monitorFileNameList, ParseIF parseIF) {
this.fileDirectory = fileDirectory;
if (monitorFileNameList != null) {
this.monitorFileNameList = monitorFileNameList;
}
this.parseIF = parseIF;
}
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 类代表了这个监听服务的注册,可以用它来获取事件的各个属性。
WatchKey key = null;
try {
//获取可用key.没有可用的就wait
key = service.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (WatchEvent<?> event : key.pollEvents()) {
log.warn(event.context() + "-" + event.kind() + "-" + event.count());
final WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
// get the filename for the event
final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) event;
final Path fileName = watchEventPath.context();
if (monitorFileNameList.stream().noneMatch(e -> e.equals(fileName.getFileName().toString()))) {
continue;
}
//创建事件
if (kind == StandardWatchEventKinds.ENTRY_CREATE) {
parseIF.parse(FileStatus.CREATE);
}
//修改事件
if (kind == StandardWatchEventKinds.ENTRY_MODIFY) {
parseIF.parse(FileStatus.MODIFY);
}
//删除事件
if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
parseIF.parse(FileStatus.DELETE);
}
}
//重置,这一步很重要,否则当前的key就不再会获取将来发生的事件
boolean valid = key.reset();
//失效状态,退出监听
if (!valid) {
break;
}
}
}
}
文件类型
1 | public enum FileStatus { |
处理函数
@FunctionalInterface
public interface ParseIF {
boolean parse(FileStatus type);
}
线程池
1 | /** |