Как выполнить итерацию файлов в каталоге в Java?
Мне нужно получить список всех файлов в каталоге, включая файлы во всех подкаталогах. Каков стандартный способ выполнения итерации каталогов с помощью Java?
Ответы
Ответ 1
Вы можете использовать File#isDirectory()
, чтобы проверить, является ли данный файл (путь) каталогом. Если это true
, вы снова вызываете тот же метод с его результатом File#listFiles()
. Это называется recursion.
Вот пример основного запуска.
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. Вместо этого вы можете использовать итеративный подход или tail-recursion, но этот другой объект;)
Ответ 2
Если вы используете 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();
}
}
}
Ответ 3
Посмотрите FileUtils класс в Apache Commons - в частности iterateFiles:
Разрешает итерацию по файлам в заданной директории (и, возможно, ее подкаталоги).
Ответ 4
Используя 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());
}
Используйте false, если вы не хотите файлы из подкаталогов.
Ответ 5
Для 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;
}
Ответ 6
Это дерево, поэтому рекурсия - ваш друг: начните с родительского каталога и вызовите метод, чтобы получить массив дочерних файлов. Итерация через дочерний массив. Если текущее значение является каталогом, передайте его рекурсивному вызову вашего метода. Если нет, обработайте файл листа соответствующим образом.
Ответ 7
Как уже отмечалось, это проблема рекурсии. В частности, вы можете посмотреть
listFiles()
В java File API здесь. Он возвращает массив всех файлов в каталоге. Используя это вместе с
isDirectory()
чтобы увидеть, нужно ли вам снова записаться, - это хорошее начало.
Ответ 8
Чтобы добавить с ответом @msandiford, как и в большинстве случаев, когда идет дерево файлов, вы можете выполнить функцию как каталог или какой-либо конкретный файл. Если u неохотно использует потоки. Можно переопределить следующие методы:
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;
}
});
Ответ 9
Вы также можете использовать 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;
}
});