IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

tondeurh

Surveiller un dossier avec javaFX, une question de ScheduledService

Noter ce billet
par , 22/05/2016 à 10h56 (1253 Affichages)
Il est parfois utile que notre application JavaFx puisse surveiller la suppression, modification ou l’ajout de nouveau fichiers dans un répertoire.
Pour cela on a les API nio avec les classes java.nio.file.WatchEvent, java.nio.file.WatchKey, java.nio.file.WatchService, java.nio.file.FileSystems, java.nio.file.Path et java.nio.file.Paths, oui cela fait beaucoup de classes, mais assez facile a mettre en œuvre.
La plus grande difficulté est que l’appel à la méthode take de la classe watchService est bloquant et cela va beaucoup nous gêner dans l’exécution de notre application JavaFx qui se verra figé lors de l’appel à cette méthode.

On va donc utiliser une classe ScheduledService et une classe Task pour permettre d’exécuter la surveillance du dossier dans un autre Thread que le Thread principal de notre application.

Ci dessous un exemple d’une simple application qui va surveiller le dossier « c:/temp » et va afficher dans une simple ListView les événements.

Nom : exemple_WatchDir.png
Affichages : 537
Taille : 23,1 Ko

Fichier FXML : FXMLDocument.fxml

Ce fichier présente une fenêtre avec deux éléments, une ListView dont le fx:id est lstFichier qui permettra l’affichage des événements et un bouton simple qui permettra de fermer l’application dont le fx:id est btnClose.

Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
<?xml version="1.0" encoding="UTF-8"?>
 
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
 
<AnchorPane id="AnchorPane" prefHeight="331.0" prefWidth="425.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxwatcher.FXMLDocumentController">
<children>
<Button fx:id="btnClose" layoutX="360.0" layoutY="281.0" onAction="#hbtnClose" text="Close" />
<ListView fx:id="lstFichier" editable="true" layoutX="14.0" layoutY="14.0" prefHeight="292.0" prefWidth="329.0" />
</children>
</AnchorPane>

Classe principale : JavaFXWatcher.java

Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
package javafxwatcher;
 
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
 
public class JavaFXWatcher extends Application {
 
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
 
        Scene scene = new Scene(root);
 
        stage.setScene(scene);
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
 
}

Fichier controleur : FXMLDocumentController.java

Le contrôleur va permettre dans la méthode « initialize » de mettre en place un watcher qui va surveiller le dossier « c:/temp ». Et une tâche planifié (Thread) qui sera déclenché toutes les 5 secondes et lit les événements déclenchés (méthode processEvents). La méthode « processEvents » permet le lire les événements du watcher et injecter ces événements dans l’observableList de la ListView.

Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package javafxwatcher;
 
import java.io.IOException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.util.Duration;
 
/**
*
* @author tondeur-h
*/
public class FXMLDocumentController implements Initializable {
  @FXML
private Button btnClose;
@FXML
private ListView<String> lstFichier;
 
 
ObservableList<String> obliste=FXCollections.observableArrayList();
WatchService ws;
Path dir;
WatchKey keys ;
 
 
@SuppressWarnings("unchecked")
static <T> WatchEvent<T> cast(WatchEvent<?> event) {
return (WatchEvent<T>)event;
}
 
@Override
public void initialize(URL url, ResourceBundle rb) {
 
  lstFichier.setItems(obliste);
 
//surveiller un répertoire
try {
    ws=FileSystems.getDefault().newWatchService();
dir= Paths.get("c:/temp");
keys = dir.register(ws, ENTRY_CREATE, ENTRY_DELETE,ENTRY_MODIFY);
  }
 
  catch (IOException ex) {
    Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
  }
 
//  tache planifiée
ScheduledService<Integer> srv=new ScheduledService<Integer>() {
    @Override
protected Task<Integer> createTask() {
return new Task<Integer>() {
 
@Override
protected Integer call() throws Exception {
processEvents();
return null;
  }
};
}
};
 
srv.setDelay(Duration.seconds(5));
srv.setPeriod(Duration.seconds(5));
srv.start();
}
 
@FXML
private void hbtnClose(ActionEvent event) {
System.exit(0);
}
 
void processEvents() {
// en attente d'un clé signalée
WatchKey key;
try {
key = ws.take();
} catch (InterruptedException x) {
return;
}
 
//type d'événement
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
// TBD - provide example of how OVERFLOW event is handled
if (kind == OVERFLOW) {
continue;
}
 
//Context for directory entry event is the file name of entry
WatchEvent<Path> ev = cast(event);
Path name = ev.context();
Path child = dir.resolve(name);
 
// afficher l’événement
obliste.add(event.kind().name()+" "+child);
}
 
//reset key and remove from set if directory no longer accessible
boolean valid = key.reset();
}
}

FIN

Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Viadeo Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Twitter Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Google Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Facebook Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Digg Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Delicious Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog MySpace Envoyer le billet « Surveiller un dossier avec javaFX, une question de ScheduledService » dans le blog Yahoo

Mis à jour 09/09/2018 à 14h45 par LittleWhite (Indentation)

Catégories
Java , Programmation

Commentaires