Ответы:
Вы можете использовать, File#isDirectory()чтобы проверить, является ли данный файл (путь) каталогом. Если это так true, то вы просто снова вызываете тот же метод с его File#listFiles()результатом. Это называется рекурсия .
Вот основной пример начала.
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());
}
}
}
Обратите внимание, что это чувствительно к тому, StackOverflowErrorкогда дерево глубже, чем может вместить стек JVM. Вы можете вместо этого использовать итеративный подход или хвостовую рекурсию , но это уже другая тема;)
NullPointerExceptionкогда файловая система меняется между вызовами isDirectoryи, listFilesкак это может случиться, если System.out.printlnблоки или вам просто не повезло. Проверка того, что вывод listFilesне равен нулю, решит это условие гонки.
java.nio.file.DirectoryStreamвы можете перебирать каталог, и его можно было бы реализовать, чтобы иметь небольшой объем памяти, но единственный способ точно сказать это контролировать использование памяти на конкретной платформе.
Если вы используете Java 1.7, вы можете использовать java.nio.file.Files.walkFileTree(...).
Например:
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();
}
}
}
Если вы используете Java 8, вы можете использовать потоковый интерфейс с 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();
}
}
}
Проверьте класс FileUtils в Apache Commons - в частности, iterateFiles :
Позволяет перебирать файлы в данном каталоге (и, необязательно, его подкаталоги).
Для Java 7+ есть также https://docs.oracle.com/javase/7/docs/api/java/nio/file/DirectoryStream.html
Пример взят из 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;
}
Это дерево, поэтому рекурсия - ваш друг: начните с родительского каталога и вызовите метод, чтобы получить массив дочерних файлов. Итерация по дочернему массиву. Если текущее значение является каталогом, передайте его рекурсивному вызову вашего метода. Если нет, обработайте файл листа соответствующим образом.
Как уже отмечалось, это проблема рекурсии. В частности, вы можете посмотреть на
listFiles()
В Java File API здесь . Возвращает массив всех файлов в каталоге. Используя это вместе с
isDirectory()
посмотреть, нужно ли вам продолжать курс, - это хорошее начало.
Чтобы добавить ответ @msandiford, так как в большинстве случаев при обходе дерева файлов вам может потребоваться выполнить функцию как каталог или посещение любого конкретного файла. Если вы не хотите использовать потоки. Следующие методы могут быть переопределены
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;
}
});
Вы также можете неправильно использовать File.list (FilenameFilter) (и варианты) для обхода файла. Короткий код и работает в ранних версиях Java, например:
// 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;
}
});