
Dans le cadre de la JSR 203, plus connu sous le nom de NIO.2, Java 7 va enfin être doté d'une toute nouvelle API pour l'accès au système de fichier, en remplacement de la classe File, qui malgré le fait qu'elle soit logiquement très utilisée, reste très problématique et incomplète dans de nombreux cas...
Mais que reproche-t-on à l'API de la classe File ?
minimum syndicalsans véritable accès à bon nombre de propriétés du système de fichier (propriétaire du fichier, groupe, permissions, ACL, attributs archive ou système, ...) voir un accès biaisé ou partiel (propriétés readable/writable/executable).
listFiles() qui se montre très peu performant dans des répertoires de taille importante).La classe File est donc destinée à être remplacée par une nouvelle classe (Path) qui viendra résoudre tous ces problèmes, ou plus précisément par tout un package : java.nio.file...
[edit] Attention : depuis la date de rédaction de cet article, l'API java.nio.file a été grandement remanié.
Les codes sources présentées ici ne sont donc plus tout à fait correct.
Cette nouvelle API prend une approche relativement différente. Plutôt que de représenter un fichier sur le système hôte (comme avec la classe File), on utilisera désormais des chemins absolu ou relatif (Path) représentant un fichier présent sur un système de fichier quelconque (FileSystem) utilisant un ou plusieurs emplacement de stockage (FileStorage).
En effet l'API est basé sur des fabriques, qui permettent de manipuler les objets au mieux sans forcément connaitre les spécificités de leurs implémentations :
// Ancien code : File file = new File("file.txt"); // Nouveau code : Path path = Paths.get("file.txt");
Par défaut on manipulera bien sûr des chemins (Path) vers des fichiers présent sur le système de fichier de l'OS hôte (FileSystem), c'est à dire sur les disques et autre périphériques de stockage (FileStorage). Mais l'API est complètement évolutive et on pourrait très bien voir arriver des implémentations utilisant d'autres "sources", comme un stockage en mémoire, directement depuis une archive, ou sur une source distante... Le tout de manière totalement transparente !
Note : de la même manière que la classe File, on représentera un chemin logique vers un fichier, même si ce dernier n'existe pas réellement.
Au niveau de son API, on retrouve une partie des fonctionnalités de la classe File, à la différence près que celles-ci utilisent désormais massivement les mécanismes d'exceptions. Ainsi on peut désormais être informé des problèmes et en avertir l'utilisateur, voir de mettre en place une solution de contournement. Fini les heures de recherche pour déterminer la cause de l'échec d'une suppression de fichier :
// Ancien code : boolean deleted = file.delete(); if (!deleted) { // Pourquoi ???? } // Nouveau code : try { path.delete(); } catch (IOException e) { // On a désormais une explication }
A noter au passage que pour faciliter la transition, la classe File se voit doter d'une nouvelle méthode toPath() permettant d'utiliser facilement les nouvelles méthodes depuis un objet File :
try { file.toPath().delete(); } catch (IOException e) { // On a désormais une explication }
La grosse différence vient surtout de l'accès aux propriétés des fichiers. Là où l'on devait se contenter des propriétés communes à l'ensemble des systèmes d'exploitations, on a désormais accès à toutes les propriétés spécifiques au système, en lecture/écriture.
Pour cela les accès aux attributs passent par des vues, qui permettent de lire les attributs et d'en modifier (lorsque cela s'avère possible). Par exemple pour accéder aux propriétés de base il faudra utiliser le code suivant :
BasicFileAttributeView basicView = path.getFileAttributeView(BasicFileAttributeView.class); if (basicView != null) { BasicFileAttributes basic = basicView.readAttributes(); System.out.println(basic.isRegularFile()); System.out.println(basic.isDirectory()); System.out.println(basic.isSymbolicLink()); System.out.println(basic.isOther()); System.out.println(basic.size()); System.out.println(basic.creationTime()); System.out.println(basic.lastAccessTime()); System.out.println(basic.lastModifiedTime()); }
Selon le système de fichier et l'OS, on pourra accéder à des propriétés différentes. Par défaut l'API propose six types de vues :
Il est ainsi possible d'accéder (et de modifier) des propriétés hautement dépendantes du système voir même du support de stockage. Bien sûr ces vues ne sont pas disponible sur tous les supports ni sur tous les systèmes...
A noter l'existence de méthodes statiques dans la classe Attributes permettant accéder directement aux attributs :
BasicFileAttributes basic = Attributes.readBasicFileAttributes(path);
Ainsi que la possibilité d'accéder aux attributs via leurs noms (précédé du nom de la vue) :
System.out.println( path.getAttribute("basic:creationTime") ); System.out.println( path.getAttribute("posix:group") ); System.out.println( path.getAttribute("owner:owner") ); System.out.println( path.getAttribute("dos:archive") );
Ce système de vue peut sembler un peu plus complexe, mais il permet une évolution simplifié et un meilleur support des sources alternatives.
La classe supporte pleinement les liens symboliques (si le système hôte les supporte bien sûr). Ainsi en plus des méthodes createSymbolicLink() et readSymbolicLink(), il est possible d'utiliser la valeur LinkOption.NOFOLLOW_LINKS pour manipuler le lien en lui-même et non pas sa cible...
On remarquera également que la classe comporte un ensemble de méthode permettant de créer différents types de flux (newInputStream(), newOutputStream(), newByteChannel()). Ceci permet de laisser au système la possibilité de fournir un type de flux plus adapté.
L'API vient également comblé un des gros problème de la classe File : le parcours des éléments d'un répertoire ou d'une arborescence pouvait s'avérer très consommateur en mémoire, car les différentes méthodes list()/listFiles() renvoient un tableau contenant tous les éléments trouvés.
Désormais on utilisera un Iterator afin de parcourir la liste des éléments un à un sans tous les charger en mémoire :
DirectoryStream<Path> directory = path.newDirectoryStream(); try { for (Path p : directory) { System.out.println(p); } } finally { directory.close(); }
On a enfin la possibilité d'utiliser une syntaxe similaire aux meta-caractères des shells pour filtrer les résultats plus facilement :
// On ne recherche que les fichiers java : DirectoryStream<Path> directory = path.newDirectoryStream("*.java");
Et la classe Files propose des méthodes permettant de parcourir récursivement une hiérarchie de répertoire via un FileVisitor, éventuellement en prenant en compte la détection des cycles...
L'API intègre également la notification de changement sur le système de fichier :
// On crée un WatchService : WatchService watcher = path.getFileSystem().newWatchService(); // Puis on l'enregistre sur un répertoire avec certain évènement : path.register(watcher, StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_MODIFY, StandardWatchEventKind.ENTRY_DELETE);
Ceci permet de surveiller les modifications apportées à un système de fichier sans avoir à le re-scanner perpétuellement. Ce mécanisme utilisera bien sûr les API de notifications spécifiques au système hôte (Notification, inotify, FSEvents) ou une implémentation pure Java s'il n'en comporte aucune.
Il ne reste plus qu'à surveiller les évènements dans un thread séparé :
while (true) { WatchKey key = watcher.take(); for (WatchEvent<?> event : key.pollEvents()) { System.out.println(event.kind() + " : " + event.context()); } key.reset(); }
http://blog.developpez.com/htsrv/trackback.php?tb_id=8061
FileStorage. Vous devez être identifié pour poster un commentaire.

Ce blog est mis à disposition sous un contrat Creative Commons BY-NC-SA.
System.gc() a encore frappé : jre 1.5, tomcat 6.0 et multi processeurs
Tutoriels Java SE
Tutoriels Java EE
Sélection du blog
Java SE/EE et Web en général
| Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
|---|---|---|---|---|---|---|
| 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 |
Copyright © 2000-2012 - www.developpez.com