Réponses:
Vous pouvez utiliser File#isDirectory()
pour tester si le fichier (chemin) donné est un répertoire. Si tel est le cas true
, il vous suffit d'appeler à nouveau la même méthode avec son File#listFiles()
résultat. C'est ce qu'on appelle la récursivité .
Voici un exemple de lancement de base.
public static void main(String... args) {
File[] files = new File("C:/").listFiles();
showFiles(files);
}
public static void showFiles(File[] files) {
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Directory: " + file.getName());
showFiles(file.listFiles()); // Calls same method again.
} else {
System.out.println("File: " + file.getName());
}
}
}
Notez que cela est sensible au StackOverflowError
moment où l'arborescence est plus profonde que ce que la pile de la JVM peut contenir. Vous voudrez peut-être utiliser une approche itérative ou une récursion de queue à la place, mais c'est un autre sujet;)
NullPointerException
produire lorsque le système de fichiers change entre l'appel à isDirectory
et listFiles
comme cela peut arriver si vous System.out.println
bloquez ou si vous êtes vraiment malchanceux. Vérifier que la sortie de listFiles
n'est pas nulle résoudrait cette condition de concurrence.
java.nio.file.DirectoryStream
vous permet d'itérer sur un répertoire et pourrait être implémenté pour avoir une petite empreinte mémoire, mais le seul moyen de le savoir avec certitude serait pour surveiller l'utilisation de la mémoire sur une plate-forme particulière.
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<Path> fv = new SimpleFileVisitor<Path>() {
@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 de flux avec java.nio.file.Files.walk(...)
:
public class WalkFileTreeExample {
public static void main(String[] args) {
try (Stream<Path> paths = Files.walk(Paths.get("/usr"))) {
paths.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Découvrez la classe FileUtils dans Apache Commons - en particulier iterateFiles :
Permet l'itération sur les fichiers dans un répertoire donné (et éventuellement ses sous-répertoires).
Pour Java 7+, il existe également https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html
Exemple tiré du Javadoc:
List<Path> listSourceFiles(Path dir) throws IOException {
List<Path> result = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.{c,h,cpp,hpp,java}")) {
for (Path entry: stream) {
result.add(entry);
}
} catch (DirectoryIteratorException ex) {
// I/O error encounted during the iteration, the cause is an IOException
throw ex.getCause();
}
return result;
}
En utilisant org.apache.commons.io.FileUtils
File file = new File("F:/Lines");
Collection<File> files = FileUtils.listFiles(file, null, true);
for(File file2 : files){
System.out.println(file2.getName());
}
Utilisez false si vous ne voulez pas de fichiers provenant de sous-répertoires.
C'est un arbre, donc la récursivité est votre ami: commencez par le répertoire parent et appelez la méthode pour obtenir un tableau de fichiers enfants. Parcourez le tableau enfant. Si la valeur actuelle est un répertoire, passez-le à un appel récursif de votre méthode. Sinon, traitez le fichier feuille de manière appropriée.
Comme indiqué, il s'agit d'un problème de récursivité. En particulier, vous voudrez peut-être regarder
listFiles()
Dans l'API de fichier java ici . Il renvoie un tableau de tous les fichiers d'un répertoire. Utiliser ceci avec
isDirectory()
voir si vous avez besoin de récidiver davantage est un bon début.
Pour ajouter avec la réponse @msandiford, comme la plupart du temps quand une arborescence de fichiers est parcourue, vous voudrez peut-être exécuter une fonction en tant que répertoire ou tout fichier particulier est visité. Si vous êtes réticent à utiliser les flux. Les méthodes suivantes remplacées peuvent être implémentées
Files.walkFileTree(Paths.get(Krawl.INDEXPATH), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException {
// Do someting before directory visit
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
// Do something when a file is visited
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
// Do Something after directory visit
return FileVisitResult.CONTINUE;
}
});
Vous pouvez également abuser de File.list (FilenameFilter) (et de ses variantes) pour la traversée de fichiers. Code court et fonctionne dans les premières versions de Java, par exemple:
// list files in dir
new File(dir).list(new FilenameFilter() {
public boolean accept(File dir, String name) {
String file = dir.getAbsolutePath() + File.separator + name;
System.out.println(file);
return false;
}
});