废话不多说,直接看代码:
FileAction.java
package com.tools.filewatch; /** * 文件变动行为枚举 * */ public enum FileAction { DELETE("ENTRY_DELETE"), CREATE("ENTRY_CREATE"), MODIFY("ENTRY_MODIFY"); private String value; FileAction(String value) { this.value = value; } public String getValue() { return value; } }
FileActionCallback.java
package com.tools.filewatch; import java.io.File; /** * 文件操作的回调方法 * */ public abstract class FileActionCallback { public void delete(File file) { }; public void modify(File file) { }; public void create(File file) { }; }
WatchDir.java
package com.tools.filewatch; import java.io.File; import java.io.IOException; import java.nio.file.*; import java.nio.file.WatchEvent.Kind; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; import static java.nio.file.LinkOption.NOFOLLOW_LINKS; /** * 文件夹监控 * */ public class WatchDir { private final WatchService watcher; private final Map<WatchKey, Path> keys; private final boolean subDir; /** * 构造方法 * * @param file 文件目录,不可以是文件 * @param subDir * @throws Exception */ public WatchDir(File file, boolean subDir, FileActionCallback callback) throws Exception { if (!file.isDirectory()) throw new Exception(file.getAbsolutePath() + "is not a directory!"); this.watcher = FileSystems.getDefault().newWatchService(); this.keys = new HashMap<WatchKey, Path>(); this.subDir = subDir; Path dir = Paths.get(file.getAbsolutePath()); if (subDir) { registerAll(dir); } else { register(dir); } processEvents(callback); } @SuppressWarnings("unchecked") static <T> WatchEvent<T> cast(WatchEvent<?> event) { return (WatchEvent<T>) event; } /** * 观察指定的目录 * * @param dir * @throws IOException */ private void register(Path dir) throws IOException { WatchKey key = dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY); keys.put(key, dir); } /** * 观察指定的目录,并且包括子目录 * * @param start * @throws IOException */ private void registerAll(final Path start) throws IOException { Files.walkFileTree(start, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { register(dir); return FileVisitResult.CONTINUE; } }); } /** * 发生文件变化的回调函数 * * @param callback */ @SuppressWarnings("rawtypes") void processEvents(FileActionCallback callback) { for (; ; ) { WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return; } Path dir = keys.get(key); if (dir == null) { System.err.println("操作未识别"); continue; } for (WatchEvent<?> event : key.pollEvents()) { Kind kind = event.kind(); // 事件可能丢失或遗弃 if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } // 目录内的变化可能是文件或者目录 WatchEvent<Path> ev = cast(event); Path name = ev.context(); Path child = dir.resolve(name); File file = child.toFile(); if (kind.name().equals(FileAction.DELETE.getValue())) { callback.delete(file); } else if (kind.name().equals(FileAction.CREATE.getValue())) { callback.create(file); } else if (kind.name().equals(FileAction.MODIFY.getValue())) { callback.modify(file); } else { continue; } // if directory is created, and watching recursively, then // register it and its sub-directories if (subDir && (kind == StandardWatchEventKinds.ENTRY_CREATE)) { try { if (Files.isDirectory(child, NOFOLLOW_LINKS)) { registerAll(child); } } catch (IOException x) { // ignore to keep sample readbale } } } boolean valid = key.reset(); if (!valid) { // 移除不可访问的目录 // 因为有可能目录被移除,就会无法访问 keys.remove(key); // 如果待监控的目录都不存在了,就中断执行 if (keys.isEmpty()) { break; } } } } }
Filewatch.java
package com.tools.filewatch; import java.io.File; public class Test { public static void main(String[] args) throws Exception { final File file = new File("C:\\test"); new Thread() { @Override public void run() { try { new WatchDir(file, true, new FileActionCallback() { @Override public void create(File file) { // TODO something... System.out.println("文件已创建\t" + file.getAbsolutePath()); } @Override public void delete(File file) { // TODO something... System.out.println("文件已删除\t" + file.getAbsolutePath()); } @Override public void modify(File file) { // TODO something... System.out.println("文件已修改\t" + file.getAbsolutePath()); } }); } catch (Exception e) { e.printStackTrace(); } } }.start(); System.out.println("正在监视文件夹:" + file.getAbsolutePath() + "的变化"); } }