파일시스템 변경을 감지해야 할 경우가 있다. 특정 디렉토리에 파일 변경(추가/삭제/수정)이 발생한 경우를 주기적으로 모니터링 해야 하는 경우이다.
기본적으로 아래의 두 가지 방법이 있다.
- WatchService 사용
- Apache Commons IO Monitor 라이브러리 사용
1. WatchService
동작 방식
WatchService를 사용하는 첫 번째 단계는 java.nio.file.FileSystem 인스턴스를 생성하는 것이다.
WatchService watchService = FileSystems.getDefault().newWatchService();
그 다음 모니터링 할 디렉토리 경로를 만들자.
Path path = Paths.get("pathToDir");
이 단계 이후에 StandardWatchEventKinds와 WatchKey를 경로에 등록해야 한다.
WatchKey watchKey = path.register(
watchService, StandardWatchEventKinds...);
StandardWatchEventKinds
- StandardWatchEventKinds.ENTRY_CREATE – 새 파일 생성이나 기존 파일의 이름 변경 등의 변경이 발생할 때
- StandardWatchEventKinds.ENTRY_MODIFY – 파일 수정이나 파일 속성이 변경될 때
- StandardWatchEventKinds.ENTRY_DELETE – 파일이 삭제되거나 이동, 이름이 변경될 때
- StandardWatchEventKinds.OVERFLOW – 이벤트가 없어질 때
예제
public class WatcherServiceSample {
public static void main(String[] args) throws IOException, InterruptedException {
WatchService watchService = FileSystems.getDefault().newWatchService();
Path path = Paths.get("/tmp");
path.register(
watchService,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("Event kind:" + event.kind() + ". File affected: " + event.context() + ".");
}
key.reset();
}
}
}
/tmp
디렉토리에 파일 변경을 감지한다. 변경이 있을 경우 로그를 찍게 된다.
실행결과
Event kind:ENTRY_MODIFY. File affected: test2.txt.
Event kind:ENTRY_DELETE. File affected: test.txt.
Event kind:ENTRY_CREATE. File affected: test3.txt.
2. Apache Commons IO Monitor
maven dependencies
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.13.0</version>
</dependency>
Apache Commons IO library는 FileAlterationListener 인터페이스에서 파일의 변경이 감지되면 콜백 메소드가 호출된다.
예제
public class CommonsIOMonitorSample {
private static final int POLL_INTERVAL = 1000;
public static void main(String[] args) throws Exception {
FileAlterationObserver observer = new FileAlterationObserver("/tmp");
FileAlterationMonitor monitor = new FileAlterationMonitor(POLL_INTERVAL);
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
@Override
public void onFileCreate(File file) {
System.out.println("File created: " + file.getName());
}
@Override
public void onFileDelete(File file) {
System.out.println("File deleted: " + file.getName());
}
@Override
public void onFileChange(File file) {
System.out.println("File changed: " + file.getName());
}
};
observer.addListener(listener);
monitor.addObserver(observer);
monitor.start();
}
}
/tmp
디렉토리에 파일 변경을 감지한다. 변경을 감지할 시간은 1초로 설정했다.
변경이 있을 경우 아래의 로그를 찍게 된다.
실행결과
File created: test.txt
File changed: test.txt
3. 비교 (WatchService vs Apache Commons IO Monitor)
WatchService
는 운영체제에서 발생하는 파일 시스템 이벤트 변경을 감지한다. 파일 시스템을 반복적으로 폴링하지 않게 한다. 시스템 리소스는 적게 먹지만 변경이 감지되는 시간은 지연이 많다.
반면에 Apache Commons IO Monitor
는 파일 시스템 위치를 특정 시간간격으로 listFiles() 메소드를 호출한다. 이러한 방법은 변경사항이 없다면 CPU를 잡아먹는 작업이다. 특정 테스트 용도로 사용하고자 한다면 Interval 시간을 줄이면 변경내역을 바로 확인할 수 있는 장점이 있지만 시스템 리소스를 많이 먹으니 조심해서 사용해야 한다.
참고자료
https://www.baeldung.com/java-nio2-watchservice
https://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library