多个事件的集合取决于用于创建/修改文件的工具。
1.用vim新建文件
MODIFIED, CREATED 事件被触发
2.用Vim修改文件
DELETED, MODIFIED, CREATED 事件被触发
3.使用Linux命令'mv'将文件从其他文件夹移动到监视文件夹
MODIFIED 事件被触发
4.使用Linux命令'cp'将文件从其他文件夹复制到监视文件夹
MODIFIED, CREATED 如果不存在同名文件则触发 CREATED 如果同名文件存在则触发
我使用 3 个地图在 for 循环中迭代 WatchEvent 中收集 CREATED/MODIFIED/DELETED 条目。然后,在这 3 个映射上运行 3 个 for 循环以确定我们需要通知的正确事件(例如:如果一个文件名出现在所有三个映射中,那么我们可以说它是一个 MODIFIED 事件)
File f = new File(sourceDir);
if (!f.exists() || !f.isDirectory()) {
LOGGER.warn("File " + sourceDir + " does not exist OR is not a directory");
return;
}
WatchService watchService = FileSystems.getDefault().newWatchService();
Path watchedDir = f.toPath();
watchedDir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
while (true) {
try {
WatchKey watchKey = watchService.take();
Thread.sleep(checkInterval);
//Events fired by Java NIO file watcher depends on the tool used
//to create/update/delete file. We need those 3 maps to collect
//all entries fired by NIO watcher. Then, make 3 loops at the end
//to determine the correct unique event to notify
final Map<String, Boolean> createdEntries = new HashMap<>();
final Map<String, Boolean> modifiedEntries = new HashMap<>();
final Map<String, Boolean> deletedEntries = new HashMap<>();
List<WatchEvent<?>> events = watchKey.pollEvents();
for (WatchEvent<?> event : events) {
if (event.kind() == OVERFLOW) {
continue;
}
WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;
WatchEvent.Kind<Path> kind = pathEvent.kind();
Path path = pathEvent.context();
String fileName = path.toString();
if (accept(fileName)) {
if (kind == ENTRY_CREATE) {
createdEntries.put(fileName, true);
} else if (kind == ENTRY_MODIFY) {
modifiedEntries.put(fileName, true);
} else if (kind == ENTRY_DELETE) {
deletedEntries.put(fileName, true);
}
}
}
long timeStamp = System.currentTimeMillis();
final Map<String, Boolean> handledEntries = new HashMap<>();
//3 for loops to determine correct event to notify
for (String key : createdEntries.keySet()) {
if (handledEntries.get(key) == null) {
Boolean modified = modifiedEntries.get(key);
Boolean deleted = deletedEntries.get(key);
if (modified != null && deleted != null) {
//A triplet of DELETED/MODIFIED/CREATED means a MODIFIED event
LOGGER.debug("File " + key + " was modified");
notifyFileModified(key, timeStamp);
} else if (modified != null) {
LOGGER.debug("New file " + key + " was created");
notifyFileCreated(key, timeStamp);
} else {
LOGGER.debug("New file " + key + " was created");
notifyFileCreated(key, timeStamp);
}
handledEntries.put(key, true);
}
}
for (String key : modifiedEntries.keySet()) {
if (handledEntries.get(key) == null) {
//Current entry survives from loop on CREATED entries. It is certain
//that we have MODIFIED event
LOGGER.debug("File " + key + " was modified");
notifyFileModified(key, timeStamp);
handledEntries.put(key, true);
}
}
for (String key : deletedEntries.keySet()) {
if (handledEntries.get(key) == null) {
//Current entry survives from two loops on CREATED/MODIFIED entries. It is certain
//that we have DELETE event
LOGGER.debug("File " + key + " was deleted");
notifyFileDeleted(key, timeStamp);
}
}
boolean valid = watchKey.reset();
if (!valid) {
break;
}
} catch (Exception ex) {
LOGGER.warn("Error while handling file events under: " + sourceDir, ex);
}
Thread.sleep(checkInterval);
}