189 votes

Comment itérer à travers les fichiers dans un répertoire et ses sous-répertoires en Java?

Je dois obtenir une liste de tous les fichiers dans un répertoire, y compris les fichiers dans tous les sous-répertoires. Quelle est la manière standard d'accomplir l'itération de répertoire avec Java?

228voto

BalusC Points 498232

Vous pouvez utiliser [File#isDirectory()](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/File.html#isDirectory()) pour tester si le fichier donné (chemin) est un répertoire. Si c'est true, alors vous appelez simplement à nouveau la même méthode avec son résultat [File#listFiles()](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/File.html#listFiles()). C'est ce qu'on appelle la récursivité.

Voici un exemple de départ de base :

package com.stackoverflow.q3154488;

import java.io.File;

public class Demo {

    public static void main(String... args) {
        File dir = new File("/chemin/vers/repertoire");
        showFiles(dir.listFiles());
    }

    public static void showFiles(File[] files) {
        for (File file : files) {
            if (file.isDirectory()) {
                System.out.println("Répertoire : " + file.getAbsolutePath());
                showFiles(file.listFiles()); // Appelle à nouveau la même méthode.
            } else {
                System.out.println("Fichier : " + file.getAbsolutePath());
            }
        }
    }
}

Remarquez que cela est sensible à StackOverflowError lorsque l'arborescence est plus profonde que la pile JVM ne peut contenir. Si vous êtes déjà sur Java 8 ou plus récent, alors il vaut mieux utiliser Files#walk() qui utilise la récursion terminale :

package com.stackoverflow.q3154488;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DemoWithJava8 {

    public static void main(String... args) throws Exception {
        Path dir = Paths.get("/chemin/vers/repertoire");
        Files.walk(dir).forEach(path -> showFile(path.toFile()));
    }

    public static void showFile(File file) {
        if (file.isDirectory()) {
            System.out.println("Répertoire : " + file.getAbsolutePath());
        } else {
            System.out.println("Fichier : " + file.getAbsolutePath());
        }
    }
}

0 votes

Merci Balus, avez-vous une idée de la profondeur que cela pourrait être en supposant de manière générale ?

10 votes

Dépend des paramètres de mémoire de votre JVM, mais en général quelque chose comme quelques milliers. Si vous pensez que vous pourriez un jour rencontrer un répertoire comme celui-ci, alors n'utilisez pas la récursion.

4 votes

Ceci est susceptible d'une NullPointerException lorsque le système de fichiers change entre l'appel à isDirectory et listFiles comme cela pourrait se produire si System.out.println bloque ou si vous avez juste vraiment de la malchance. Vérifier que la sortie de listFiles n'est pas nulle résoudrait cette condition de concurrence.

96voto

msandiford Points 6297

Si vous utilisez Java 1.7, vous pouvez utiliser java.nio.file.Files.walkFileTree(...).

Par exemple :

public class WalkFileTreeExample {

  public static void main(String[] args) {
    Path p = Paths.get("/usr");
    FileVisitor fv = new SimpleFileVisitor() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
        System.out.println(file);
        return FileVisitResult.CONTINUE;
      }
    };

    try {
      Files.walkFileTree(p, fv);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

Si vous utilisez Java 8, vous pouvez utiliser l'interface stream avec java.nio.file.Files.walk(...):

public class WalkFileTreeExample {

  public static void main(String[] args) {
    try (Stream paths = Files.walk(Paths.get("/usr"))) {
      paths.forEach(System.out::println);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}

2 votes

Y a-t-il un moyen avec les flux pour mettre un point de contrôle lorsqu'un nouveau répertoire est parcouru et exécuter une fonction ?

0 votes

Files.walk(somePath) vous permettra de parcourir tout l'arbre de fichiers et de répertoires accessibles à partir de ce répertoire racine. Si vous avez besoin de traiter uniquement certains fichiers, par exemple en fonction de leur extension, vous pouvez utiliser un filter avec PathMatcher que vous avez configuré pour glob:**.xml pour exclure tous les fichiers non-XML aux étapes ultérieures du pipeline.

28voto

Ben J Points 2360

Découvrez la classe FileUtils dans Apache Commons - spécifiquement iterateFiles:

Permet l'itération sur les fichiers dans le répertoire donné (et éventuellement ses sous-répertoires).

5 votes

Cette API n'est pas vraiment en streaming (si vous vous souciez de l'utilisation de la mémoire), elle génère d'abord une collection, puis renvoie un itérateur dessus: return listFiles(directory, fileFilter, dirFilter).iterator();

0 votes

Bonne option pour Java 1.6.

0 votes

D'accord avec @GiliNachum. FileUtils par Apache collecte d'abord tous les fichiers et en donne un itérateur. Cela peut être néfaste pour les ressources si vous avez une quantité énorme de fichiers.

3voto

duffymo Points 188155

C'est un arbre, donc la récursion est votre amie : commencez par le répertoire parent et appelez la méthode pour obtenir un tableau de fichiers enfants. Parcourez le tableau d'enfants. Si la valeur actuelle est un répertoire, passez-la à un appel récursif de votre méthode. Sinon, traitez le fichier feuille de manière appropriée.

2voto

Chimmy Points 102

Comme indiqué, il s'agit d'un problème de récursion. En particulier, vous voudrez peut-être regarder

listFiles() 

Dans l'API de fichiers en java ici. Cela renvoie un tableau de tous les fichiers dans un répertoire. Utiliser cela en conjonction avec

isDirectory()

Pour voir si vous devez vous récursivement plus loin est un bon début.

0 votes

Ce lien pourrait être utile car celui dans la réponse est cassé.

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