Liste récursive des fichiers en Java

Comment puis-je récursivement lister tous les fichiers sous un répertoire en Java? Le cadre fournit-il un utilitaire?

J’ai vu beaucoup d’implémentations de hacky. Mais aucun du framework ou nio

Java 8 fournit un bon stream pour traiter tous les fichiers d’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 stream, vous pouvez effectuer toutes les opérations de stream intéressantes sur le résultat, telles que la limitation, le regroupement, le mappage, la sortie anticipée, etc.

MISE À JOUR : Je vous ferai remarquer que Files.find contient également un BiPredicate qui pourrait être plus efficace si vous devez vérifier les atsortingbuts des fichiers.

 Files.find(Paths.get(path), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile()) .forEach(System.out::println); 

Notez que bien que JavaDoc élude que cette méthode puisse être plus efficace que Files.walk, elle est effectivement identique, la différence de performance peut être observée si vous récupérez également des atsortingbuts de fichier dans votre filtre. En fin de compte, si vous devez filtrer les atsortingbuts, utilisez Files.find , sinon utilisez Files.walk , principalement 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. Découvrez le projet Github qui contient des résultats et un cas de test .

FileUtils a des méthodes iterateFiles et listFiles . Essayez-les. (de commons-io )

Edit: Vous pouvez vérifier ici un benchmark de différentes approches. Il semble que l’approche commons-io soit lente, alors choisissez d’abord les plus rapides (si c’est important)

// Prêt à courir

 import java.io.File; public class Filewalker { public void walk( Ssortingng 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(Ssortingng[] args) { Filewalker fw = new Filewalker(); fw.walk("c:\\" ); } } 

Java 7 aura has Files.walkFileTree :

Si vous fournissez un sharepoint départ et un visiteur de fichier, il invoquera diverses méthodes sur le visiteur du fichier lorsqu’il parcourt le fichier dans l’arborescence de fichiers. Nous nous attendons à ce que les gens l’utilisent s’ils développent une copie récursive, un mouvement récursif, une suppression récursive ou une opération récursive qui définit des permissions ou effectue une autre opération sur chacun des fichiers.

Il existe maintenant un didacticiel Oracle complet sur cette question .

Aucune bibliothèque externe requirejse.
Renvoie une collection pour que vous puissiez faire ce que vous voulez après l’appel.

 public static Collection listFileTree(File dir) { Set fileTree = new HashSet(); if(dir==null||dir.listFiles()==null){ return fileTree; } for (File entry : dir.listFiles()) { if (entry.isFile()) fileTree.add(entry); else fileTree.addAll(listFileTree(entry)); } return fileTree; } 

J’irais avec quelque chose comme:

 public void list(File file) { System.out.println(file.getName()); File[] children = file.listFiles(); for (File child : children) { list(child); } } 

Le System.out.println est juste là pour indiquer de faire quelque chose avec le fichier. il n’y a pas besoin de différencier les fichiers et les répertoires, car un fichier normal aura simplement zéro enfant.

il suffit de l’écrire vous-même en utilisant la récursivité simple:

 public List addFiles(List files, File dir) { if (files == null) files = new LinkedList(); if (!dir.isDirectory()) { files.add(dir); return files; } for (File file : dir.listFiles()) addFiles(files, file); return files; } 

Je préfère utiliser une queue plutôt qu’une récursivité pour ce type de traversée simple:

 List allFiles = new ArrayList(); Queue dirs = new LinkedList(); dirs.add(new File("/start/dir/")); while (!dirs.isEmpty()) { for (File f : dirs.poll().listFiles()) { if (f.isDirectory()) { dirs.add(f); } else if (f.isFile()) { allFiles.add(f); } } } 

Avec Java 7, vous pouvez utiliser la classe suivante:

 import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.atsortingbute.BasicFileAtsortingbutes; public class MyFileIterator extends SimpleFileVisitor { public MyFileIterator(Ssortingng path) throws Exception { Files.walkFileTree(Paths.get(path), this); } @Override public FileVisitResult visitFile(Path file, BasicFileAtsortingbutes atsortingbutes) throws IOException { System.out.println("File: " + file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAtsortingbutes atsortingbutes) throws IOException { System.out.println("Dir: " + dir); return FileVisitResult.CONTINUE; } } 

Je pense que cela devrait faire le travail:

 File dir = new File(dirname); Ssortingng[] files = dir.list(); 

De cette façon, vous avez des fichiers et des répertoires. Maintenant, utilisez la récursivité et faites la même chose pour les dirs (la classe File a la méthode isDirectory() ).

Dans Java 8, nous pouvons maintenant utiliser l’utilitaire Files pour parcourir une arborescence de fichiers. Très simple.

 Files.walk(root.toPath()) .filter(path -> !Files.isDirectory(path)) .forEach(path -> System.out.println(path)); 

Outre la traversée récursive, on peut également utiliser une approche basée sur Visitor.

Le code ci-dessous utilise l’approche basée sur Visitor pour la traversée. Il est attendu que l’entrée dans le programme soit le répertoire racine à parcourir.

 public interface Visitor { void visit(DirElement d); void visit(FileElement f); } public abstract class Element { protected File rootPath; abstract void accept(Visitor v); @Override public Ssortingng toSsortingng() { return rootPath.getAbsolutePath(); } } public class FileElement extends Element { FileElement(final Ssortingng path) { rootPath = new File(path); } @Override void accept(final Visitor v) { v.visit(this); } } public class DirElement extends Element implements Iterable { private final List elemList; DirElement(final Ssortingng path) { elemList = new ArrayList(); rootPath = new File(path); for (File f : rootPath.listFiles()) { if (f.isDirectory()) { elemList.add(new DirElement(f.getAbsolutePath())); } else if (f.isFile()) { elemList.add(new FileElement(f.getAbsolutePath())); } } } @Override void accept(final Visitor v) { v.visit(this); } public Iterator iterator() { return elemList.iterator(); } } public class ElementWalker { private final Ssortingng rootDir; ElementWalker(final Ssortingng dir) { rootDir = dir; } private void traverse() { Element d = new DirElement(rootDir); d.accept(new Walker()); } public static void main(final Ssortingng[] args) { ElementWalker t = new ElementWalker("C:\\temp"); t.traverse(); } private class Walker implements Visitor { public void visit(final DirElement d) { System.out.println(d); for(Element e:d) { e.accept(this); } } public void visit(final FileElement f) { System.out.println(f); } } } 

Vous pouvez utiliser le code ci-dessous pour obtenir une liste de fichiers d’un dossier ou d’un répertoire spécifique de manière récursive.

 public static void main(Ssortingng args[]) { recusiveList("D:"); } public static void recursiveList(Ssortingng path) { File f = new File(path); File[] fl = f.listFiles(); for (int i = 0; i < fl.length; i++) { if (fl[i].isDirectory() && !fl[i].isHidden()) { System.out.println(fl[i].getAbsolutePath()); recusiveList(fl[i].getAbsolutePath()); } else { System.out.println(fl[i].getName()); } } } 

Ce code est prêt à fonctionner

 public static void main(Ssortingng... args) { File[] files = new File("C:/").listFiles(); if (files != null) getFile(files); } public static void getFile(File[] files) { for (File file : files) { if (file.isDirectory()) { getFile(file.listFiles()); } else { System.out.println("File: " + file.toSsortingng()); } } } 

BFS non récursif avec une seule liste (exemple particulier recherchant des fichiers * .eml):

  final FileFilter filter = new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory() || file.getName().endsWith(".eml"); } }; // BFS recursive search List queue = new LinkedList(); queue.addAll(Arrays.asList(dir.listFiles(filter))); for (ListIterator itr = queue.listIterator(); itr.hasNext();) { File file = itr.next(); if (file.isDirectory()) { itr.remove(); for (File f: file.listFiles(filter)) itr.add(f); } } 

Ma version (bien sûr j’aurais pu utiliser la version intégrée de Java 8 ;-)):

 public static List findFilesIn(File rootDir, Predicate predicate) { ArrayList collected = new ArrayList<>(); walk(rootDir, predicate, collected); return collected; } private static void walk(File dir, Predicate filterFunction, List collected) { Stream.of(listOnlyWhenDirectory(dir)) .forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction))); } private static File[] listOnlyWhenDirectory(File dir) { return dir.isDirectory() ? dir.listFiles() : new File[]{}; } private static List addAndReturn(List files, File toAdd, Predicate filterFunction) { if (filterFunction.test(toAdd)) { files.add(toAdd); } return files; } 

Exemple de sortie de fichiers * .csv dans la recherche récursive de répertoires Sous-répertoires à l’aide de Files.find () à partir de java.nio:

 Ssortingng path = "C:/Daten/ibiss/ferret/"; logger.debug("Path:" + path); try (Stream fileList = Files.find(Paths.get(path), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toSsortingng().endsWith("csv"))) { List someThingNew = fileList.sorted().map(Ssortingng::valueOf).collect(Collectors.toList()); for (Ssortingng t : someThingNew) { t.toSsortingng(); logger.debug("Filename:" + t); } } 

Publier cet exemple, car j’avais du mal à comprendre comment passer le paramètre filename dans l’exemple # 1 donné par Bryan, en utilisant foreach sur Stream-result –

J’espère que cela t’aides.

Voici une solution simple mais parfaitement fonctionnelle utilisant la recursion :

 public static List listFiles(Ssortingng rootDirectory) { List files = new ArrayList<>(); listFiles(rootDirectory, files); return files; } private static void listFiles(String path, List collectedFiles) { File root = new File(path); File[] files = root.listFiles(); if (files == null) { return; } for (File file : files) { if (file.isDirectory()) { listFiles(file.getAbsolutePath(), collectedFiles); } else { collectedFiles.add(file.toPath()); } } } 
  private void fillFilesRecursively(File file, List resultFiles) { if (file.isFile()) { resultFiles.add(file); } else { for (File child : file.listFiles()) { fillFilesRecursively(child, resultFiles); } } } 

Basé sur la réponse emstackur. Voici une solution fonctionnant dans JSP sans aucune bibliothèque externe, vous pouvez donc la placer presque n’importe où sur votre serveur:

  <%@ page session="false" %> <%@ page import="java.util.*" %> <%@ page import="java.io.*" %> <%@ page contentType="text/html; charset=UTF-8" %> <%! public List files = new ArrayList(); /** Fills files array with all sub-files. */ public void walk( File root ) { File[] list = root.listFiles(); if (list == null) return; for ( File f : list ) { if ( f.isDirectory() ) { walk( f ); } else { files.add(f.getAbsolutePath()); } } } %> <% files.clear(); File jsp = new File(request.getRealPath(request.getServletPath())); File dir = jsp.getParentFile(); walk(dir); String prefixPath = dir.getAbsolutePath() + "/"; %> 

Ensuite, vous faites juste quelque chose comme:

  
    <% for (String file : files) { %> <% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
  • <%=file.replace(prefixPath, "")%>
  • <% } %> <% } %>