323 votes

Lister récursivement des fichiers en Java

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

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 ?

419voto

Brett Ryan Points 4905

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 .

7 votes

Un de ces exemples qui peut montrer la magie de la programmation fonctionnelle même aux débutants.

2 votes

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.

1 votes

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.

167voto

Bozho Points 273663

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)

45 votes

FYI/TLDR : si vous voulez juste lister tous les fichiers récursivement sans filtrage, faites FileUtils.listFiles(dir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)dir est un objet File qui pointe vers le répertoire de base.

2 votes

Vous pouvez envisager d'utiliser listFilesAndDirs() comme listFiles() ne renvoie pas de dossiers vides.

1 votes

@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.

142voto

stacker Points 34209

// 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:\\" );
    }

}

9 votes

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 -> . .

2 votes

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é.

0 votes

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.

71voto

yawn Points 2823

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 .

0 votes

Et il ne notifie jamais la fin de la marche.

19voto

Stefan Schmidt Points 872

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.

6 votes

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 ."

0 votes

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 ; }

0 votes

Pour moi, c'est la réponse la plus concise et la plus récursive.

Prograide.com

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.

Powered by:

X