Lister les fichiers dans un répertoire
Vous pouvez facilement lister les noms de fichiers de tous les fichiers d’un répertoire à l’aide de la méthode list() de la classe File. Si vous souhaitez obtenir des fichiers autres que de simples noms de fichiers, vous pouvez utiliser sa méthode listFiles(). C'est très simple, le plus difficile est de savoir comment traiter la liste renvoyée. Au lieu d'utiliser de longs itérateurs externes traditionnels, nous utilisons des expressions fonctionnelles élégantes pour parcourir cette liste. Ici, nous devons également utiliser la nouvelle interface CloseableStream du JDK et certaines fonctions de haut niveau associées.
Le code suivant répertorie les noms de tous les fichiers du répertoire actuel.
Copiez le code comme suit :
Fichiers.list(Chemins.get("."))
.forEach(System.out::println);
Si vous souhaitez lister d'autres répertoires, vous pouvez remplacer "." par le chemin complet du répertoire auquel vous souhaitez accéder.
Ici, nous utilisons d'abord la méthode get() de Paths pour créer une instance Path via une chaîne. Ensuite, nous obtenons un objet ClosableStream via la méthode list() de la classe d'outils Files, et nous pouvons l'utiliser pour parcourir tous les fichiers du répertoire. Nous utilisons ensuite l'itérateur interne forEach() pour imprimer le nom du fichier. Examinons d'abord certains des résultats de sortie de ce code : listez les fichiers et sous-répertoires du répertoire courant.
Copiez le code comme suit :
./aSampleFiles.txt
./bac
./fpij
...
Si nous voulons uniquement obtenir les sous-répertoires du répertoire courant, pas les fichiers, nous pouvons utiliser la méthode filter() :
Copiez le code comme suit :
Fichiers.list(Chemins.get("."))
.filter (Fichiers :: isDirectory)
.forEach(System.out::println);
La méthode ilter() filtre les répertoires du flux de fichiers. Nous transmettons une référence à la méthode isDirectory de la classe Files au lieu de transmettre une expression lambda. Rappelez-vous que la méthode filter() nécessite un type Predicate qui renvoie une valeur booléenne, et cette méthode est parfaite. Enfin, nous utilisons un itérateur interne pour imprimer le nom du répertoire. Le programme imprimera les sous-répertoires du répertoire actuel.
Copiez le code comme suit :
./bac
./fpij
./sortir
...
Il est beaucoup plus simple d'écrire de cette façon et permet d'économiser beaucoup de code par rapport à l'ancienne méthode d'écriture en Java. Voyons comment lister les fichiers correspondant à un certain modèle.
Lister les fichiers spécifiés dans un répertoire
Java propose depuis longtemps une variante de la méthode list() pour filtrer les noms de fichiers. Cette version de la méthode list() accepte un paramètre de type FilenameFilter. Cette interface n'a qu'une seule méthode accept(), qui accepte deux paramètres : File dir (représentant le répertoire) et String name (représentant le nom du fichier). Si la méthode accept() renvoie true, le nom du fichier apparaîtra dans la liste renvoyée, sinon il n'apparaîtra pas. Implémentons cette méthode.
L'approche habituelle consiste à transmettre une instance d'une classe interne anonyme qui implémente l'interface FilenameFilter à la méthode list(). Par exemple, voyons comment utiliser cette méthode pour renvoyer le fichier .java dans le répertoire fpij.
Copiez le code comme suit :
fichiers String[] finaux =
new File("fpij").list(new java.io.FilenameFilter() {
public boolean accept (répertoire final du fichier, nom final de la chaîne) {
return name.endsWith(".java");
}
});
System.out.println(fichiers);
Cela prend vraiment du temps et des efforts pour écrire quelques lignes de code. Ce type de code est trop bruyant : créer des objets, appeler des fonctions, définir des classes internes anonymes, intégrer des méthodes dans des classes, etc. Nous n'avons plus à supporter cette douleur, il suffit de passer une expression lambda qui accepte deux paramètres et renvoie un bolléen. Le compilateur Java s'occupera du reste.
L'exemple précédent pourrait simplement remplacer les éléments internes anonymes par une expression lambda, mais il existe une marge d'optimisation supplémentaire. Le nouvel outil DirectoryStream peut nous aider à parcourir plus efficacement de grandes structures de répertoires. Essayons cette méthode. Il s'agit d'une variante de la méthode newDirectoryStream() qui accepte un filtre supplémentaire.
Copiez le code comme suit :
Fichiers.newDirectoryStream(
Paths.get("fpij"), chemin -> path.toString().endsWith(".java"))
.forEach(System.out::println);
De cette façon, nous nous débarrassons de la classe interne anonyme et rendons le code encombrant, concis et clair. Le résultat des deux versions est le même. Imprimons le fichier spécifié.
Ce code affichera uniquement les fichiers .java dans le répertoire spécifié. Voici une partie de sa sortie :
Copiez le code comme suit :
fpij/Compare.java
fpij/IterateString.java
fpij/ListDirs.java
...
Nous filtrons les fichiers en fonction des noms de fichiers. Il peut également être facilement filtré par attributs de fichier, par exemple si le fichier est exécutable, lisible, inscriptible, etc. Pour ce faire, vous avez besoin d'une méthode listFiles(), qui accepte un paramètre de type FileFilter. Nous utilisons toujours des expressions lambda au lieu de créer des classes internes anonymes. Regardons maintenant un exemple de liste de tous les fichiers cachés dans le répertoire actuel.
Copiez le code comme suit :
final File[] files = new File(".").listFiles(file -> file.isHidden());
Si nous exploitons un grand répertoire, nous pouvons utiliser DirectoryStream au lieu d'appeler directement la méthode sur File.
La signature de l'expression lambda que nous transmettons à la méthode listFiles() est la même que la signature de la méthode accept() de l'interface FileFilter. Cette expression lambda accepte un paramètre d'une instance de fichier. Dans cet exemple, le nom du paramètre est file. Si le fichier a des attributs cachés, il renvoie vrai, sinon il renvoie faux.
En fait, le code peut être encore simplifié ici. Nous ne transmettons pas d'expressions lambda. Passer une référence de méthode rendra le code plus concis :
Copiez le code comme suit :
new File(".").listFiles(File::isHidden);
Nous l'avons d'abord implémenté à l'aide d'expressions lambda, puis nous l'avons refactorisé pour qu'il soit plus concis à l'aide de références de méthodes. Si nous écrivons du nouveau code, nous devons bien sûr utiliser cette méthode concise. Si une implémentation aussi soignée pouvait être trouvée rapidement, nous donnerions certainement la priorité à son utilisation. Il existe un dicton appelé "Faites-le fonctionner d'abord, puis améliorez-le". Après l'avoir clarifié, nous considérerons la simplicité et les performances pour l'optimisation.
Nous utilisons un exemple pour filtrer les fichiers spécifiés d'un répertoire. Voyons comment parcourir les sous-répertoires d'un répertoire spécifié.