Sunday, August 07, 2011

Java 7: WatchService for File Change Notification

The Watch Service API in JDK7 allows you to watch a directory for changes to files and receive notification events when a file is added, deleted or modified. You no longer need to poll the file system for changes which is inefficient and doesn't scale well.

The code below shows how you would use the Watch Service API. First, you have to create a WatchService for the file system and then register the directory you want to monitor with it. You have to specify which events (create, modify or delete) you are interested in receiving. Then start an infinite loop to wait for events. When an event occurs, a WatchKey is placed into the watch service's queue and you have to call take to retrieve it. You can then query the key for events and print them out.

/**
 * Watch the specified directory
 * @param dirname the directory to watch
 * @throws IOException
 * @throws InterruptedException
 */
public static void watchDir(String dir)
    throws IOException, InterruptedException{

  //create the watchService
  final WatchService watchService = FileSystems.getDefault().newWatchService();

  //register the directory with the watchService
  //for create, modify and delete events
  final Path path = Paths.get(dir);
  path.register(watchService,
            StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY,
            StandardWatchEventKinds.ENTRY_DELETE);

  //start an infinite loop
  while(true){

    //remove the next watch key
    final WatchKey key = watchService.take();

    //get list of events for the watch key
    for (WatchEvent<?> watchEvent : key.pollEvents()) {

      //get the filename for the event
      final WatchEvent<Path> ev = (WatchEvent<Path>)watchEvent;
      final Path filename = ev.context();

      //get the kind of event (create, modify, delete)
      final Kind<?> kind = watchEvent.kind();

      //print it out
      System.out.println(kind + ": " + filename);
    }

    //reset the key
    boolean valid = key.reset();

    //exit loop if the key is not valid
    //e.g. if the directory was deleted
      if (!valid) {
          break;
      }
  }
}
Demo:
$ java Watcher &
$ touch foo
ENTRY_CREATE: foo
$ echo hello >> foo
ENTRY_MODIFY: foo
$ rm foo
ENTRY_DELETE: foo

6 comments:

  1. How to watch whether a particular file in a directory has changed or not?

    ReplyDelete
  2. Hello, I got a problem. When I delete the directory which is watched by watch service before emptying it. I get errors of FileNotFound.

    ReplyDelete
  3. hey please tell me how to know the path of the file that is being manipulated in the directory.
    for example i am monitoring a folder named pracs
    a file named text.txt is modified within that folder
    then how to know the path of the entire file being manipulated i.e. pracs/text.txt

    ReplyDelete
    Replies
    1. List> events = watchKey.pollEvents();
      for(WatchEvent event : events){
      String absoluteFilePath = event.context().toString();
      }

      Delete
  4. Thank you for this, it was very useful !

    ReplyDelete
  5. Hi Shariff i want the code as when we are changing the text in a text file and after save it should show what is the text changed or added in that text file. Please help me in what way the code should be.
    Thanks in Advance..
    Karthik

    ReplyDelete