Antworten:
Sie können File#isDirectory()damit testen, ob die angegebene Datei (Pfad) ein Verzeichnis ist. Wenn dies der Fall ist true, rufen Sie dieselbe Methode mit ihrem File#listFiles()Ergebnis erneut auf. Dies wird als Rekursion bezeichnet .
Hier ist ein grundlegendes Kickoff-Beispiel.
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());
}
}
}
Beachten Sie, dass dies empfindlich ist, StackOverflowErrorwenn der Baum tiefer ist, als der Stapel der JVM aufnehmen kann. Vielleicht möchten Sie stattdessen einen iterativen Ansatz oder eine Schwanzrekursion verwenden, aber das ist ein anderes Thema;)
NullPointerExceptionin dem sich das Dateisystem zwischen dem Aufruf von isDirectoryund dem Blockieren ändert oder Sie einfach Pech haben. Wenn Sie überprüfen, ob die Ausgabe von nicht null ist, wird diese Racebedingung gelöst. listFilesSystem.out.printlnlistFiles
java.nio.file.DirectoryStreamkönnen Sie über ein Verzeichnis iterieren und könnten so implementiert werden, dass sie einen geringen Speicherbedarf haben, aber der einzige Weg, dies sicher zu sagen, wäre um die Speichernutzung auf einer bestimmten Plattform zu überwachen.
Wenn Sie Java 1.7 verwenden, können Sie verwenden java.nio.file.Files.walkFileTree(...).
Beispielsweise:
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();
}
}
}
Wenn Sie Java 8 verwenden, können Sie die Stream-Schnittstelle verwenden mit 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();
}
}
}
Schauen Sie sich die FileUtils- Klasse in Apache Commons an - speziell iterateFiles :
Ermöglicht die Iteration der Dateien im angegebenen Verzeichnis (und optional der Unterverzeichnisse).
Für Java 7+ gibt es auch https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html
Beispiel aus dem 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;
}
Verwenden von 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());
}
Verwenden Sie false, wenn Sie keine Dateien aus Unterverzeichnissen möchten.
Es ist ein Baum, also ist Rekursion Ihr Freund: Beginnen Sie mit dem übergeordneten Verzeichnis und rufen Sie die Methode auf, um ein Array von untergeordneten Dateien abzurufen. Durchlaufen Sie das untergeordnete Array. Wenn der aktuelle Wert ein Verzeichnis ist, übergeben Sie ihn an einen rekursiven Aufruf Ihrer Methode. Wenn nicht, verarbeiten Sie die Blattdatei entsprechend.
Wie bereits erwähnt, ist dies ein Rekursionsproblem. Insbesondere möchten Sie vielleicht einen Blick darauf werfen
listFiles()
In der Java-Datei-API hier . Es gibt ein Array aller Dateien in einem Verzeichnis zurück. Verwenden Sie dies zusammen mit
isDirectory()
zu sehen, ob Sie weiter zurückgreifen müssen, ist ein guter Anfang.
Um mit @msandiford Antwort hinzuzufügen, möchten Sie in den meisten Fällen, wenn ein Dateibaum durchlaufen wird, eine Funktion als Verzeichnis ausführen oder eine bestimmte Datei wird besucht. Wenn Sie keine Streams verwenden möchten. Die folgenden überschriebenen Methoden können implementiert werden
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;
}
});
Sie können File.list (FilenameFilter) (und Varianten) auch zum Durchlaufen von Dateien missbrauchen. Funktionscode und funktioniert in frühen Java-Versionen, zB:
// 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;
}
});