Comment lister récursivement tous les fichiers d'un répertoire en Java ? Le framework fournit-il un utilitaire ?
J'ai vu beaucoup d'implémentations bricolées. Mais aucune du cadre ou nio
Comment lister récursivement tous les fichiers d'un répertoire en Java ? Le framework fournit-il un utilitaire ?
J'ai vu beaucoup d'implémentations bricolées. Mais aucune du cadre ou nio
Java 8 fournit un flux agréable pour traiter tous les fichiers dans un arbre.
Files.walk(Paths.get(path))
.filter(Files::isRegularFile)
.forEach(System.out::println);
Cela fournit un moyen naturel de parcourir les fichiers. Comme il s'agit d'un flux, vous pouvez effectuer toutes les opérations de flux sur le résultat, comme la limitation, le regroupement, le mappage, la sortie anticipée, etc.
UPDATE : Je pourrais souligner qu'il y a aussi Fichiers.find qui prend un BiPredicate qui pourrait être plus efficace si vous avez besoin de vérifier les attributs des fichiers.
Files.find(Paths.get(path),
Integer.MAX_VALUE,
(filePath, fileAttr) -> fileAttr.isRegularFile())
.forEach(System.out::println);
Notez que, bien que la JavaDoc laisse entendre que cette méthode pourrait être plus efficace que l'option Files.walk il est effectivement identique, la différence de performance peut être observée si vous récupérez également les attributs du fichier dans votre filtre. En fin de compte, si vous avez besoin de filtrer sur les attributs, utilisez Fichiers.find sinon, utilisez Files.walk surtout parce qu'il y a des surcharges et que c'est plus pratique.
TESTS : Comme demandé, j'ai fourni une comparaison des performances de plusieurs des réponses. Consultez le Projet Github qui contient les résultats et un cas de test .
Un de ces exemples qui peut montrer la magie de la programmation fonctionnelle même aux débutants.
Comment les performances de cette méthode se comparent-elles à celles des méthodes pré-Java 8 ? Ma méthode actuelle de traversée des répertoires est trop lente et je cherche quelque chose qui puisse l'accélérer.
Je suis en train de rédiger des tests contenant la plupart des variantes des réponses fournies. Jusqu'à présent, il semble que l'utilisation de Files.walk
avec un flux parallèle est le meilleur, suivi de près par Files.walkFileTree
qui n'est que marginalement plus lent. La réponse acceptée utilisant commons-io est de loin la plus lente selon mes tests, soit 4 fois plus lente.
FileUtils ont iterateFiles
y listFiles
méthodes. Essayez-les. (de commun-io )
Edit : Vous pouvez Vérifiez ici pour un benchmark des différentes approches. Il semble que l'approche commons-io soit lente, alors choisissez quelques-unes des approches les plus rapides. d'ici (si cela compte)
FYI/TLDR : si vous voulez juste lister tous les fichiers récursivement sans filtrage, faites FileUtils.listFiles(dir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)
où dir
est un objet File qui pointe vers le répertoire de base.
Vous pouvez envisager d'utiliser listFilesAndDirs()
comme listFiles()
ne renvoie pas de dossiers vides.
@MikeFHay En regardant le code de FileUtils, je pense que cela pourrait être FileUtils.listFiles(dir, true, true)
. en utilisant FileUtils.listFiles(dir, null, true)
lèvera une exception, tandis que FileUtils.listFiles(dir, true, null)
listera tous les fichiers sans regarder dans les sous-répertoires.
// Prêt à fonctionner
import java.io.File;
public class Filewalker {
public void walk( String path ) {
File root = new File( path );
File[] list = root.listFiles();
if (list == null) return;
for ( File f : list ) {
if ( f.isDirectory() ) {
walk( f.getAbsolutePath() );
System.out.println( "Dir:" + f.getAbsoluteFile() );
}
else {
System.out.println( "File:" + f.getAbsoluteFile() );
}
}
}
public static void main(String[] args) {
Filewalker fw = new Filewalker();
fw.walk("c:\\" );
}
}
Attention, pour les liens symboliques qui pointent vers un chemin plus haut dans la hiérarchie des chemins, la méthode ne se terminera jamais. Considérons un chemin avec un lien symbolique qui pointe vers -> .
.
Il s'agit essentiellement d'une mauvaise implémentation de Files.walkFileTree. Je recommanderais aux gens de regarder FIles.walkFileTree au lieu d'essayer de l'implémenter eux-mêmes... Il a un traitement pour le problème exact que @BrettRyan a signalé.
Merci d'avoir inclus import java.io.File ;. De nombreux exemples oublient d'inclure les espaces de noms ou même les types de données, ce qui fait de l'exemple un point de départ pour un voyage de découverte. Ici, cet exemple est prêt à être exécuté. Merci.
Java 7 aura a Files.walkFileTree :
Si vous fournissez un point de départ et un visiteur de fichier, il invoquera diverses méthodes sur le visiteur de fichier au fur et à mesure qu'il parcourt le fichier dans l'arborescence. Nous nous attendons à ce que les gens l'utilisent s'ils développent une copie récursive, un déplacement récursif, une suppression récursive ou une opération récursive qui définit les autorisations ou effectue une autre opération sur chacun des fichiers.
Il y a maintenant tout un Tutoriel Oracle sur cette question .
Je choisirais quelque chose comme :
public void list(File file) {
System.out.println(file.getName());
File[] children = file.listFiles();
for (File child : children) {
list(child);
}
}
System.out.println est juste là pour indiquer qu'il faut faire quelque chose avec le fichier. Il n'est pas nécessaire de faire la différence entre les fichiers et les répertoires, puisqu'un fichier normal n'aura simplement aucun enfant.
D'après la documentation de listFiles()
: "Si ce nom de chemin abstrait ne désigne pas un répertoire, alors cette méthode retourne null
."
Variante améliorée public static Collection<File> listFileTree(File dir) { if (null == dir || !dir.isDirectory()) { return Collections.emptyList() ; } final Set<File> fileTree = new HashSet<File>() ; for (File entry : dir.listFiles()) { if (entry.isFile()) { fileTree.add(entry) ; } else { fileTree.addAll(listFileTree(entry)) ; } } return fileTree ; } }. } return fileTree ; }
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
3 votes
Je viens de terminer Résultats des tests qui fournissent des tests de performance pour la plupart des réponses. Sans surprise, toutes les réponses basées sur NIO sont les plus performantes. La réponse commons-io est clairement la moins performante avec une durée d'exécution deux fois plus longue.
2 votes
Java8 : Files.walk ?