Список файлов в каталоге
Вы можете легко перечислить имена всех файлов в каталоге, используя метод list() класса File. Если вы хотите получить файлы, отличные от просто имен файлов, вы можете использовать метод listFiles(). Это очень просто, самое сложное — как обработать возвращенный список. Вместо использования традиционных длинных внешних итераторов мы используем элегантные функциональные выражения для фактического обхода этого списка. Здесь нам также придется использовать новый интерфейс CloseableStream JDK и некоторые связанные с ним функции высокого порядка.
В следующем коде перечислены имена всех файлов в текущем каталоге.
Скопируйте код кода следующим образом:
Files.list(Paths.get("."))
.forEach(System.out::println);
Если вы хотите перечислить другие каталоги, вы можете заменить «.» полным путем к каталогу, к которому вы хотите получить доступ.
Здесь мы сначала используем метод get() класса Paths для создания экземпляра Path через строку. Затем мы получаем объект ClosableStream с помощью метода list() класса инструмента Files и можем использовать его для обхода всех файлов в каталоге. Затем мы используем внутренний итератор forEach() для вывода имени файла. Давайте сначала посмотрим на некоторые выходные результаты этого кода: перечислим файлы и подкаталоги в текущем каталоге.
Скопируйте код кода следующим образом:
./aSampleFiles.txt
./бин
./fpij
...
Если мы хотим получить только подкаталоги текущего каталога, а не файлы, мы можем использовать метод filter():
Скопируйте код кода следующим образом:
Files.list(Paths.get("."))
.filter(Files::isDirectory)
.forEach(System.out::println);
Метод ilter() фильтрует каталоги из файлового потока. Мы передаем ссылку на метод isDirectory класса Files вместо передачи лямбда-выражения. Напомним, что методу filter() требуется тип Predicate, который возвращает логическое значение, и этот метод как раз подходит. Наконец, мы используем внутренний итератор для вывода имени каталога. Программа распечатает подкаталоги текущего каталога.
Скопируйте код кода следующим образом:
./бин
./fpij
./выход
...
Такой способ написания намного проще и позволяет сэкономить много кода по сравнению со старым способом написания на Java. Давайте посмотрим, как составить список файлов, соответствующих определенному шаблону.
Список файлов, указанных в каталоге
Java уже давно предоставляет вариант метода list() для фильтрации имен файлов. Эта версия метода list() принимает параметр типа FilenameFilter. Этот интерфейс имеет только один метод Accept(), который принимает два параметра: каталог файла (представляющий каталог) и имя строки (представляющее имя файла). Если метод Accept() возвращает true, имя файла появится в возвращаемом списке, в противном случае — нет. Давайте реализуем этот метод.
Обычный подход заключается в передаче экземпляра анонимного внутреннего класса, реализующего интерфейс FilenameFilter, методу list(). Например, давайте посмотрим, как использовать этот метод для возврата файла .java в каталог fpij.
Скопируйте код кода следующим образом:
окончательные файлы String[] =
новый File("fpij").list(new java.io.FilenameFilter() {
public boolean Accept (конечный каталог файла, окончательное имя строки) {
вернуть name.endsWith(".java");
}
});
System.out.println(файлы);
Написание нескольких строк кода действительно требует времени и усилий. Такой код слишком «шумный»: создание объектов, вызов функций, определение анонимных внутренних классов, встраивание методов в классы и т. д. Нам больше не нужно терпеть эту боль, просто передаем лямбда-выражение, которое принимает два параметра и возвращает булловское значение. Обо всем остальном позаботится компилятор Java.
В предыдущем примере можно было бы просто заменить анонимные внутренние компоненты лямбда-выражением, но есть возможности для дальнейшей оптимизации. Новый инструмент DirectoryStream может помочь нам более эффективно перемещаться по большим структурам каталогов. Давайте попробуем этот метод. Это вариант метода newDirectoryStream(), который принимает дополнительный фильтр.
Скопируйте код кода следующим образом:
Files.newDirectoryStream(
Paths.get("fpij"), path -> path.toString().endsWith(".java"))
.forEach(System.out::println);
Таким образом мы избавляемся от анонимного внутреннего класса и делаем громоздкий код кратким и понятным. Вывод обеих версий одинаков. Распечатаем указанный файл.
Этот код будет выводить файлы .java только в указанном каталоге. Вот часть его вывода:
Скопируйте код кода следующим образом:
fpij/Compare.java
fpij/IterateString.java
fpij/ListDirs.java
...
Мы фильтруем файлы по именам файлов. Их также можно легко фильтровать по атрибутам файла, например, является ли файл исполняемым, доступным для чтения, доступным для записи и т. д. Для этого вам понадобится метод listFiles(), который принимает параметр типа FileFilter. Мы по-прежнему используем лямбда-выражения вместо создания анонимных внутренних классов. Теперь давайте рассмотрим пример вывода списка всех скрытых файлов в текущем каталоге.
Скопируйте код кода следующим образом:
окончательный File[] files = новый File(".").listFiles(file -> file.isHidden());
Если мы работаем с большим каталогом, мы можем использовать DirectoryStream вместо прямого вызова метода File.
Подпись лямбда-выражения, которое мы передаем методу listFiles(), совпадает с подписью метода Accept() интерфейса FileFilter. Это лямбда-выражение принимает параметр экземпляра File. В этом примере имя параметра — file. Если файл имеет скрытые атрибуты, он возвращает true, в противном случае — false.
Фактически, здесь код можно еще более упростить. Мы не передаем лямбда-выражения. Передача ссылки на метод сделает код более кратким:
Скопируйте код кода следующим образом:
новый файл(".").listFiles(File::isHidden);
Сначала мы реализовали его с использованием лямбда-выражений, а затем реорганизовали его, сделав его более кратким, используя ссылки на методы. Если мы пишем новый код, нам, конечно, следует использовать этот лаконичный метод. Если бы такую изящную реализацию можно было найти на раннем этапе, мы бы наверняка отдали предпочтение ее использованию. Есть поговорка: «Сначала заставь это работать, а потом улучши». Сначала дайте коду работать. После того, как мы это прояснили, мы рассмотрим простоту и производительность для оптимизации.
Мы используем пример для фильтрации указанных файлов из каталога. Давайте посмотрим, как перемещаться по подкаталогам в указанном каталоге.