Java étant un langage multi-plateforme, le principe est de recevoir les événements (ChangeNotification sous Windows ou inotify sous Linux) du système d'exploitation. L'enregistrement à ces services est pris en charge par la JVM qui retransmets les messages à nos applications.
Note: la JVM et le JDK 1.7 doivent etre mis à jour pour utiliser la class WatchService.
Utiliser WatchService pour surveiller le dossier
La class FolderSpyWorker regroupe les fonctions d'enregistrement et de notification des événements. Les fonctions de WachService seront utilisées au travers d'une class Runnable permettant l'appel via un Thread.Le dossier à surveiller est transmis dans le constructeur de la class. Pour l'exemple, les notifications sont simplement affichées dans la console, les événements peuvent prendre 4 valeurs distinctes:
- ENTRY_CREATE: un nouveau fichier est crée,
- ENTRY_MODIFY: un fichier est modifié dans le répertoire,
- ENTRY_DELETE: suppression d'un fichier,
- OVERFLOW: evenement perdu ou non traité.
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Surveiller les changements dans un dossier
* @author Axel
* @see http://www.fobec.com/java/1126/detecter-changements-fichiers-dans-dossier.html
*/
public class FolderSpyWorker implements Runnable {
private Path path = null;
/**
* Constructor
* @param pathname String dossier à surveiller
*/
public FolderSpyWorker(String pathname) {
this.path = Paths.get(pathname);
System.out.println("Start FolderSpy on:" + pathname);
}
/**
* Worker
*/
public void run() {
WatchService watchService = null;
try {
watchService = this.path.getFileSystem().newWatchService();
//Enregistrer les opérations à surveiller
this.path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_DELETE);
WatchKey watchKey;
// boucle sans fin
while (!Thread.interrupted()) {
watchKey = watchService.take();
//traiter les evenements
for (WatchEvent<?> event : watchKey.pollEvents()) {
String fileName = event.context().toString();
if (StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())) {
System.out.println("new file create "+fileName);
} else if (StandardWatchEventKinds.ENTRY_MODIFY.equals(event.kind())) {
System.out.println(fileName+" has been modified");
} else if (StandardWatchEventKinds.ENTRY_DELETE.equals(event.kind())) {
System.out.println(fileName+" has been deleted");
} else if (StandardWatchEventKinds.OVERFLOW.equals(event.kind())) {
System.out.println("Strange event");
continue;
}
}
//se place en attente de message
watchKey.reset();
}
} catch (InterruptedException ex) {
try {
if (watchService!=null) watchService.close();
System.out.println("Stop FolderSpy");
} catch (IOException ex1) {
Logger.getLogger(FolderSpyWorker.class.getName()).log(Level.SEVERE, null, ex1);
}
} catch (Exception ex) {
Logger.getLogger(FolderSpyWorker.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Notifier les modifications avec un Thread
Le thread permet d'isoler et contrôler plus facilement les opérations. Dans cet exemple, le dossier à surveiller est passé dans le constructeur de FolderSpyWorker à savoir c:temp. Le thread démarre et s'arrête tout seul au bout de 30 secondes. Les événements de modification, de création et de suppression sont notifiés dans la console.
/**
* Exemple: Surveiller un répertoire avec un thread
* @author Axel
* @see http://www.fobec.com/java/1126/detecter-changements-fichiers-dans-dossier.html
*/
public class FolderSpySample {
public static void main(String[] args) throws InterruptedException {
//Créer le worker
FolderSpyWorker folderSpyWorker=new FolderSpyWorker("c://temp//");
//Créer le thred
Thread folderSpyThread = new Thread(folderSpyWorker);
//Lancer le thread
folderSpyThread.start();
//Patienter 30 secondes
Thread.sleep(30000);
//Fermer le Thread
folderSpyThread.interrupt();
}
}