Я пытаюсь распечатать каталоги, содержащиеся в определенном каталоге под названием «Книги». Я использую интерфейс 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». Что я делаю не так?
Отредактировано. Извини за это.
Вы неправильно используете FilenameFilter
. dir
указывает на "C:/users/Dell/Desktop/Books"
и name
на записи. Вы вообще не смотрите на name
.
Всегда полезно внимательно прочитать 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. Спасибо.
Э-э, ок. Просто перезапустите код и добавьте оператор печати в метод принятия интерфейса FilenameFilter. getName возвращает имя файла/каталога, а не абсолютный путь... Тем не менее, я попробую альтернативный API, который вы предложили.
Я бы сначала попробовал, и если после перезаписи он все еще не работает, задайте новый вопрос - таким образом, у нас будет полный набор инструментов Files API, и нам не придется иметь дело со странностями старого. имеет. Но сначала я бы потратил некоторое время на отладку, обычно это быстрее, чем написание вопроса по SO :) — удачи!
@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")
Вы неправильно используете 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»? Я открыт для любой критики и лучших предложений. Спасибо.
Исправлять нечего, молодцы!
Вы смешали File
и NIO Path/Files
. Вам было бы лучше оставить все java.io
, если вам нужно сохранить зависимость от File
, или предпочтительно использовать весь java.nio
код, как предложено rzwitserloot и в улучшенном ответе Lesiak (Files.find
с глубиной = 1)
Попробую сделать это @DuncG, спасибо. Опубликую еще один ответ, который вы также можете раскритиковать.
Вот ответ, который использует пакет 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, ты раскритиковал мой ответ, поэтому я почувствовал необходимость написать его так, как он предложил...
Ваши 2 фрагмента идентичны. Пожалуйста, отредактируйте вопрос.