Возникла проблема с распечаткой каталогов после использования интерфейса FilenameFilter

Я пытаюсь распечатать каталоги, содержащиеся в определенном каталоге под названием «Книги». Я использую интерфейс FilenameFilter для фильтрации только каталогов, исключая файлы. Мой код выглядит следующим образом:

package dirspkg;

import java.io.File;
import java.util.Arrays;
import java.util.Objects;
import java.io.FilenameFilter;

public class DirectoryDemo {
    public static void main(String... args) {
        File directory = new File("C:/users/Dell/Desktop/Books");

        Arrays.stream(Objects.requireNonNull(directory.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return dir.isDirectory() && dir.getName().startsWith("j");
            }
        }))).forEach(System.out::println);
    }
}

Код ничего не выводит, но на самом деле у меня есть каталоги, начинающиеся с «j» в каталоге книг. Мне просто нужны каталоги, начинающиеся с буквы «j». Что я делаю не так?

Ваши 2 фрагмента идентичны. Пожалуйста, отредактируйте вопрос.

rzwitserloot 25.06.2024 15:10

Отредактировано. Извини за это.

DammyD 25.06.2024 15:14

Вы неправильно используете FilenameFilter. dir указывает на "C:/users/Dell/Desktop/Books" и name на записи. Вы вообще не смотрите на name.

Lesiak 25.06.2024 15:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
117
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Всегда полезно внимательно прочитать javadoc. Кроме того, отладка — это вещь: все, что вам нужно сделать, чтобы разобраться в этом, — это напечатать значение name в вашем фильтре или установить там точку останова.

Причина, по которой это не работает: абсолютные пути.

Согласно javadoc listFiles: ответ getName() включает в себя весь путь. Итак, строка будет C:/users/Dell/Desktop/Books/journey by moonlight. Которое не начинается с маленькой буквы j.

Исправить это

Выбросьте этот код в мусорное ведро. java.io.File устарел (например, устарел - не используйте. Базовые библиотеки Java не добавляют @Deprecated к своим устаревшим материалам по несколько сомнительным причинам. Дело в том, что то, что он не отмечен @Deprecated, не означает, что он не устарел. ).

Новый API доступен в java.nio.file.Files. Это то, что вы хотите использовать. Он проясняет всю эту проблему с абсолютным путем (он основан на объектах Path, которые имеют гораздо более понятные методы для «Мне просто нужно простое имя файла» и «Мне нужен весь путь»), и в отличие от java.io.File он сообщает об ошибках в разумной форме ( бросая вместо возврата false, который легко пропустить и означает, что невозможно узнать, что не так). Он также гораздо более функционален: вы можете работать с программными ссылками, он поддерживает файловые системы и т. д.

Я рассмотрю API java.nio.file.Files. Спасибо.

DammyD 25.06.2024 15:21

Э-э, ок. Просто перезапустите код и добавьте оператор печати в метод принятия интерфейса FilenameFilter. getName возвращает имя файла/каталога, а не абсолютный путь... Тем не менее, я попробую альтернативный API, который вы предложили.

DammyD 25.06.2024 15:38

Я бы сначала попробовал, и если после перезаписи он все еще не работает, задайте новый вопрос - таким образом, у нас будет полный набор инструментов Files API, и нам не придется иметь дело со странностями старого. имеет. Но сначала я бы потратил некоторое время на отладку, обычно это быстрее, чем написание вопроса по SO :) — удачи!

rzwitserloot 25.06.2024 15:42

@rzwitserloot Это не ваш обычный подробный ответ, поскольку строка не использует абсолютный путь C:/users/Dell/Desktop/Books/journey by moonlight. Это не работает, потому что метод Accept вызывается с помощью dir=new File("C:/users/Dell/Desktop/Books") и name = "journey by moonlight", а OP проверяет, является ли родительский каталог каталогом, и использует dir.getName() вместо name - следовательно, тест терпит неудачу, поскольку тест "Books".startsWith("j")

DuncG 28.06.2024 13:52
Ответ принят как подходящий

Вы неправильно используете FilenameFilter. dir указывает на "C:/users/Dell/Desktop/Books" и название записи. Вы вообще не смотрите на имя.

Это даст вам что-то вроде:

Arrays.stream(Objects.requireNonNull(directory.listFiles((dir, name) -> {
    var testedFile = new File(dir, name);
    return testedFile.isDirectory() && name.startsWith("j");
}))).forEach(System.out::println);

Обратите внимание, что File.isDirectory может работать медленно (и это противоречит намерению FilenameFilter проверять только имена файлов)

Новые файловые API улучшают обе

Path dir = Paths.get("C:/users/Dell/Desktop/Books");

BiPredicate<Path, BasicFileAttributes> dirStartingWithJ = (path, attrs)
                -> attrs.isDirectory() && path.getFileName().toString().startsWith("j");
try (Stream<Path> dirs = Files.find(dir, 1, dirStartingWithJ)) {
    dirs.forEach(System.out::println);
}

Я очень ценю этот вклад. Ниже приведен код, который я использовал для решения проблемы. Пожалуйста, не стесняйтесь критиковать или указывать на любые недостатки.

package dirspkg;

import java.io.File;
import java.io.FilenameFilter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;

public class DirectoryDemo {
    public static void main(String... args) {
// Get file handle for Books directory
        File directory = new File("C:/users/Dell/Desktop/Books");

// Create stream from array of File objects contained in Books directory
// that have been filtered for directories whose name begin with the letter 'j' 
// and print the name of those directories out via the stream
        Arrays.stream(Objects.requireNonNull(directory.listFiles(new FilenameFilter() {
    // Check that for each file object in Books directory that it is a 
    // directory and its name begins with the letter 'j'
            @Override
            public boolean accept(File dir, String name) {
                Path path = Paths.get(dir + "\\" + name);
                return Files.isDirectory(path) && path.getFileName().toString().startsWith("j");
            }
        }))).forEach(System.out::println);
    }
}

Мой результат выглядит следующим образом:

C:\users\Dell\Desktop\Books\java books
C:\users\Dell\Desktop\Books\javascript
C:\users\Dell\Desktop\Books\julia programming

Какие подкаталоги в каталоге «Книги» начинаются с буквы «j»? Я открыт для любой критики и лучших предложений. Спасибо.

Исправлять нечего, молодцы!

Marce Puente 26.06.2024 14:17

Вы смешали File и NIO Path/Files. Вам было бы лучше оставить все java.io, если вам нужно сохранить зависимость от File, или предпочтительно использовать весь java.nio код, как предложено rzwitserloot и в улучшенном ответе Lesiak (Files.find с глубиной = 1)

DuncG 28.06.2024 14:02

Попробую сделать это @DuncG, спасибо. Опубликую еще один ответ, который вы также можете раскритиковать.

DammyD 01.07.2024 16:03

Вот ответ, который использует пакет java.nio.file:

package dirspkg;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class DirectoryDemo2 {
    public static void main(String[] args) {
        Path path = Path.of("C:/users/Dell/Desktop/Books");
        try {
            Files.find(path, 2, (dirPath, attrs) -> attrs.isDirectory()
                    && dirPath.getFileName().toString().startsWith("j")).forEach(System.out::println);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Работает отлично. Готов услышать другие мнения по коду. По сути, это код, написанный одним из участников (@Lesiak, кажется)

Или просто примите ответ Лесиака, см. Что мне делать, когда кто-то отвечает на мой вопрос

DuncG 01.07.2024 16:32

Принял.... :)

DammyD 02.07.2024 13:25

@DuncG, ты раскритиковал мой ответ, поэтому я почувствовал необходимость написать его так, как он предложил...

DammyD 02.07.2024 13:33

Другие вопросы по теме