方法入口
public class DirMonitor implements Runnable{
@Override
public void run() {
new NowFileChangeProc().startMonitor("监听的目录");
}
}
文件变动事件
public class NowFileChangeProc {
public void startMonitor(String dir) {
if (dir == null) {
String msg = "error, the monitor dir con't is null!";
ErrReporter.report(msg);
return;
}
final File file = new File(dir);
new Thread(new Runnable() {
public void run() {
try {
new WatchDir(file, true, new FileActionCallback() {
@Override
public void create(File file) {
if (file.isDirectory()) {
// 创建文件夹不处理
return;
}
String msg = "File create \t" + file.getAbsolutePath();
// if(file.renameTo(file)) {
// msg += "\r\n add to queue";
String absolutePath = file.getAbsolutePath();
if(absolutePath.endsWith("txt")) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
UploadsQueue.addCurrent(new File(absolutePath));
}
}, 1000);
}
Configs.sysLog.info(msg+"---------监听新文件夹创建");
}
@Override
public void delete(File file) {
String msg = "File delete \t" + file.getAbsolutePath();
Configs.sysLog.info(msg);
}
@Override
public void modify(File file) {
String msg = "File update \t" + file.getAbsolutePath();
String absolutePath = file.getAbsolutePath();
if(absolutePath.endsWith("txt")) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
UploadsQueue.addCurrent(new File(absolutePath));
}
}, 1000);
}
Configs.sysLog.info(msg+"---------监听新文件夹移动");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
Configs.sysLog.info("--------------------------------------------------\nMonitoring:" + file.getAbsolutePath() + "\t >>> ");
}
public static void main(String[] args) throws Exception {
new NowFileChangeProc().startMonitor("D:\\upload");
}
}
文件操作的回调方法
/**
* 文件操作的回调方法
*/
public abstract class FileActionCallback {
public void delete(File file) {
};
public void modify(File file) {
};
public void create(File file) {
};
}
文件变动行为枚举
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;
}
}
文件监听目录
/**
* 文件夹监控
*
*/
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()) {
Exception newExce = new Exception(file.getAbsolutePath() + "is not a directory!");
Configs.sysLog.info(ExceptionUtil.getExceptionTxt(newExce));
throw newExce;
}
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);
}
/**
* 观察指定的目录,并且包括子目录
*/
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;
}
});
}
/**
* 发生文件变化的回调函数
*/
@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) {
// 操作未识别
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()) {
String msg = "WatchDir break because keys isEmpty";
Configs.sysLog.info(msg);
break;
}
}
}
}
}