Перейти к основному содержимому

Список файлов в каталоге в Java

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы рассмотрим различные способы перечисления файлов в каталоге .

2. Листинг

Если мы хотим вывести список всех файлов в каталоге и пропустить дальнейшее изучение подкаталогов, мы можем просто использовать java.io.File#listFiles :

public Set<String> listFilesUsingJavaIO(String dir) {
return Stream.of(new File(dir).listFiles())
.filter(file -> !file.isDirectory())
.map(File::getName)
.collect(Collectors.toSet());
}

3. DirectoryStream

Однако в Java 7 появилась более быстрая альтернатива File #listFiles, называемая DirectoryStream .

Давайте посмотрим, как выглядит эквивалент:

public Set<String> listFilesUsingDirectoryStream(String dir) throws IOException {
Set<String> fileList = new HashSet<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(dir))) {
for (Path path : stream) {
if (!Files.isDirectory(path)) {
fileList.add(path.getFileName()
.toString());
}
}
}
return fileList;
}

Мы легко видим, что, хотя DirectoryStream может быть быстрее, он не является частью Stream API и не совсем подходит для работы с ним.

Кроме того, DirectoryStream требует, чтобы мы закрыли ресурс, то есть обернули его с помощью try-with-resources .

4. Листинг в Java 8

Если мы используем Java 8, мы можем извлечь выгоду из нового метода java.nio.file.Files#list .

Он возвращает лениво заполненный поток записей в каталоге.

Давайте посмотрим на простой пример:

public Set listFilesUsingFilesList(String dir) throws IOException {
try (Stream stream = Files.list(Paths.get(dir))) {
return stream
.filter(file -> !Files.isDirectory(file))
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toSet());
}
}

Если нам требуется своевременная утилизация ресурсов файловой системы, мы должны использовать оператор try-with-resources . Таким образом, мы гарантируем, что поток будет закрыт сразу после завершения операций с потоком.

5. Ходьба

Или мы можем вывести список всех файлов в каталоге, пройдя его до настроенной глубины .

Давайте используем java.nio.file.Files#walk для вывода списка всех файлов в каталоге на заданную глубину:

public Set<String> listFilesUsingFileWalk(String dir, int depth) throws IOException {
try (Stream<Path> stream = Files.walk(Paths.get(dir), depth)) {
return stream
.filter(file -> !Files.isDirectory(file))
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toSet());
}
}

Конечно, не забудьте использовать try-with-resources , чтобы дескриптор файла для каталога закрывался должным образом.

Или, если мы хотим иметь больший контроль над тем, что происходит с каждым посещенным файлом, мы также можем предоставить реализацию посетителя:

public Set<String> listFilesUsingFileWalkAndVisitor(String dir) throws IOException {
Set<String> fileList = new HashSet<>();
Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
if (!Files.isDirectory(file)) {
fileList.add(file.getFileName().toString());
}
return FileVisitResult.CONTINUE;
}
});
return fileList;
}

Это удобно, когда мы хотим выполнять дополнительное чтение, перемещение или удаление файлов по ходу работы.

6. Заключение

В этом кратком руководстве мы рассмотрели различные способы отображения файлов в каталоге.

Как всегда, полный исходный код примеров доступен на GitHub .