Vous aimez ce que vous lisez sur ce blog ?
Envie d'aller plus loin avec véritable formation d'expertise en Java ?
Venez suivre ma formation Masterclasse Expertise Java !

"Même un développeur experimenté a besoin de continuer à apprendre. Et dans cette formation... j'ai appris beaucoup !" - A.G., Java Champion

Sessions intra-entreprises sur demande : contact[at]mokatech.net.
Inscrivez-vous vite !

Filesystem notifications with Java 7

A developer sought yesterday some advice about the best way to implement the following feature in his application : how to react, as quickly as possible, to the creation of a special "lock file" in a well-known directory.
His current implementation uses a polling thread calling the File.exists() method every few hundreds ms, which is a best-effort tradeoff between notification speed and unnecessary CPU burning.

As of Java 7, there is a better way to achieve this.
The java.nio.file package provides a WatchService that plugs directly into the underlying OS's file notification system, allowing the application to be asychronously notified of filesystem-related events of certain types (file creation, modification, deletion, etc.).

This WatchService works alot like the dreaded NIO channel Selector, but is fortunately simpler : first declare which events you are interested in, then loop on a blocking method to wait for some event to occur, process it as required, rince and repeat.

Here is what I quickly coded as a proof-of-concept.

public class LockFileDetector {
 
    public static void main(String[] args) throws IOException {
        if (args.length < 1) {
            System.out.println("Usage : LockFileDetector <file>");
            System.exit(0);
        }
 
        new LockFileDetector().detectLockFile(args[0]);
    }
 
    public void detectLockFile(String lockFilePath) throws IOException {
 
        // Plug into the OS's filesystem notification service
        WatchService watcher = FileSystems.getDefault().newWatchService();
 
        // Get Paths for the not-yet-existing lock file and its parent directory
        Path lockFile = Paths.get(lockFilePath);
        Path lockFileDir = lockFile.getParent();
 
        // Ask to be notified if a file is created in the directory
        lockFileDir.register(watcher, ENTRY_CREATE);
 
        // While the lock file does not exist...
        WatchKey watchKey;
        _watchLoop:
        while (!Thread.currentThread().isInterrupted()) {
 
            // Wait for some event to occur in the directory
            try {
                watchKey = watcher.take();
                if (!watchKey.isValid()) {
                    continue;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
 
            // Cycle through the events
            final List<WatchEvent<?>> watchEvents = watchKey.pollEvents();
            for (WatchEvent<?> event : watchEvents) {
 
                // Ensure it is a creation event
                if (event.kind().equals(ENTRY_CREATE)) {
 
                    // Compute the new file's full path
                    Path createdFileRelativePath = (Path) event.context();
                    Path createdFileAbsolultePath = lockFileDir.resolve(createdFileRelativePath);
 
                    // Is it our lock file ?
                    if (createdFileAbsolultePath.equals(lockFile)) {
                        System.out.println("Lock file detected !");
                    }
                }
            }
            watchKey.reset();
 
        }
 
        watcher.close();
    }
 
}

This code works pretty well on my Linux-powered laptop, there is no noticeable delay between the file creation and the notification.

If you want to test it on your own platform, run the code with the lock file path as an argument (see below), then create the expected file. The notification should appear in the console.

java LockFileDetector /home/olivier/Desktop/lock.lck

Hope that helps !


Commentaires

1. Le mercredi 18 mai 2011, 09:26 par franarge

Thanks Olivier for the POC :-)
Is there a way to be notified when a file creation is finished ? I mean when the file has finished to be written on the file system.

2. Le lundi 19 septembre 2011, 12:58 par ddave

En cherchant des exemples, je suis tombé sur <a href="http://jpathwatch.wordpress.com">jpathwatch</a> qui lui est compatible Java 5.

Sachant que jpathwatch est compatible au niveau interface et plus complet (support Mac, plus de modifications).

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.