Jawaban:
Anda dapat menggunakan File#isDirectory()untuk menguji apakah file (path) yang diberikan adalah direktori. Jika ini true, maka Anda cukup memanggil metode yang sama lagi dengan File#listFiles()hasilnya. Ini disebut rekursi .
Inilah contoh dasar kickoff.
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());
}
}
}
Perhatikan bahwa ini sensitif StackOverflowErrorketika pohon lebih dalam dari yang bisa ditumpuk oleh JVM. Anda mungkin ingin menggunakan pendekatan berulang atau rekursi ekor sebagai gantinya, tapi itu subjek lain;)
NullPointerExceptionketika sistem file berubah antara panggilan ke isDirectorydan listFilesseperti yang mungkin terjadi jika System.out.printlnblok atau Anda hanya benar-benar beruntung. Memeriksa bahwa output listFilesbukan nol akan menyelesaikan kondisi balapan itu.
java.nio.file.DirectoryStreammemungkinkan Anda untuk beralih ke direktori, dan dapat diimplementasikan untuk memiliki jejak memori yang kecil tetapi satu-satunya cara untuk memastikannya adalah untuk memantau penggunaan memori pada platform tertentu.
Jika Anda menggunakan Java 1.7, Anda dapat menggunakan java.nio.file.Files.walkFileTree(...).
Sebagai contoh:
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();
}
}
}
Jika Anda menggunakan Java 8, Anda dapat menggunakan antarmuka stream dengan 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();
}
}
}
Lihat kelas FileUtils di Apache Commons - khususnya iterateFiles :
Mengizinkan pengulangan atas file dalam direktori yang diberikan (dan juga subdirektori opsional).
Untuk Java 7+, ada juga https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html
Contoh yang diambil dari 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;
}
Ini pohon, jadi rekursi adalah teman Anda: mulailah dengan direktori induk dan panggil metode untuk mendapatkan array File anak. Iterate melalui array anak. Jika nilai saat ini adalah direktori, berikan kepada panggilan metode Anda secara rekursif. Jika tidak, proses file daun dengan tepat.
Sebagaimana dicatat, ini adalah masalah rekursi. Secara khusus, Anda mungkin ingin melihatnya
listFiles()
Di java File API di sini . Ini mengembalikan array dari semua file dalam direktori. Menggunakan ini bersama dengan
isDirectory()
untuk melihat apakah Anda perlu berulang lagi adalah awal yang baik.
Untuk menambahkan dengan @msandiford jawab, karena sebagian besar waktu ketika pohon file berjalan Anda mungkin ingin menjalankan fungsi sebagai direktori atau file tertentu dikunjungi. Jika Anda enggan menggunakan stream. Metode berikut yang ditimpa dapat diimplementasikan
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;
}
});
Anda juga dapat menyalahgunakan File.list (FilenameFilter) (dan varian) untuk traversal file. Kode pendek dan berfungsi dalam versi java awal, misalnya:
// 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;
}
});