Monitor directory changes
Quartz定时器 or Timer + Thread:开启线程定时去读取文件内容,查看文件内容是否发生变化,但对于文件内容过大或者过于复杂的(不推荐),或者通过定时检查文件的修改时间lastModifyTime,但是可能出现问题(不推荐),还有通过读取文件流生成MD5对应的MD5码,如果MD5不同则文件发生变化,对于大型文件也有问题,适合小文件。
JDK watch:使用JDK 7自带的 watch。
Commons-io.monitor:File Monitor - a component for monitoring file system events。
JDK watch
有三种监听事件类型,ENTRY_CREATE、ENTRY_DELETE、ENTRY_MODIFY。Watch只能监控目录,而不能监听某个具体的文件,需手动实现监听具体的文件。如果直接监听文件,则会报错 NotDirectoryException。
public static void jdkWatchDirectory() {
// define a folder root
Path myDir = Paths.get("D:/deploy");
try {
WatchService watcher = myDir.getFileSystem().newWatchService();
myDir.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey watckKey = watcher.take();
while (true) {
List<WatchEvent<?>> events = watckKey.pollEvents();
for (WatchEvent event : events)
if (event.kind() == StandardWatchEventKinds.ENTRY_MODIFY)
System.out.println("Modify: " + event.context().toString());
}
} catch (Exception e) {
System.out.println("Error: " + e.toString());
}
}
使用JDK Watch方式监控Directory,当文件内容发生变更时,有可能会触发两次MODIFY。
Commons-io Monitor
Commons-io Monitor class as follows:
FileAlterationListener Interface: A listener that receives events of file system modifications.
public interface FileAlterationListener {
/**
* File system observer started checking event.
*
* @param observer The file system observer
*/
void onStart(final FileAlterationObserver observer);
/**
* Directory created Event.
*
* @param directory The directory created
*/
void onDirectoryCreate(final File directory);
/**
* Directory changed Event.
*
* @param directory The directory changed
*/
void onDirectoryChange(final File directory);
/**
* Directory deleted Event.
*
* @param directory The directory deleted
*/
void onDirectoryDelete(final File directory);
/**
* File created Event.
*
* @param file The file created
*/
void onFileCreate(final File file);
/**
* File changed Event.
*
* @param file The file changed
*/
void onFileChange(final File file);
/**
* File deleted Event.
*
* @param file The file deleted
*/
void onFileDelete(final File file);
/**
* File system observer finished checking event.
*
* @param observer The file system observer
*/
void onStop(final FileAlterationObserver observer);
}
FileAlterationListenerAdaptor:a dapter ,fileAlterationListener implementation that does nothing.rewrite required methods。
example
public class FileListener extends FileAlterationListenerAdaptor {
@Override
public void onFileChange(File file) {
if (file.getName().contains("mail_profile.xml")) {
// TODO do something
}
System.out.println("Modify:" + file.getAbsolutePath());
}
@Override
public void onStart(FileAlterationObserver observer) {
super.onStart(observer);
}
@Override
public void onStop(FileAlterationObserver observer) {
super.onStop(observer);
}
public static void main(String[] args) throws Exception{
String targetDirectory = "D:\\deploy";
long listeningInterval = TimeUnit.SECONDS.toMillis(2);
FileAlterationObserver observer = new FileAlterationObserver(targetDirectory);
observer.addListener(new FileListener());
FileAlterationMonitor monitor = new FileAlterationMonitor(listeningInterval, observer);
monitor.start();
}
}
Monitor directory "d:\deploy" file changes. 如果想监听某类文件的变化,需要添加FileFilter。
/**
* Construct an observer for the specified directory and file filter.
*
* @param directoryName the name of the directory to observe
* @param fileFilter The file filter or null if none
*/
public FileAlterationObserver(String directoryName, FileFilter fileFilter) {
this(new File(directoryName), fileFilter);
}
implementation
String targetDirectory = "D:\\deploy";
long listeningInterval = TimeUnit.SECONDS.toMillis(2);
IOFileFilter fileFilter = FileFilterUtils.and(
FileFilterUtils.fileFileFilter(),
FileFilterUtils.suffixFileFilter(".xml"),
FileFilterUtils.nameFileFilter("mail_profile.xml"));
Collection<File> files = FileUtils.listFiles(new File(rootDir),fileFilter, TrueFileFilter.INSTANCE);
System.out.println(files);
FileAlterationObserver observerFilter = new FileAlterationObserver(targetDirectory, fileFilter);
observerFilter.addListener(new FileListener());
FileAlterationMonitor monitor = new FileAlterationMonitor(listeningInterval, observerFilter );
monitor.start();
但是FileFilter没有生效,并且整个目录的文件变化都未触发事件。所以只能不加FileFilter,并且在onFileChange中判断需要监听的具体类型或具体某个文件。