Исключение Java NullPointerException при вызове listFiles() в каталоге

#java #nullpointerexception

#java #исключение nullpointerexception

Вопрос:

У меня есть ряд папок, содержащих книги на сервере, к которым я обращаюсь с помощью этого фрагмента кода. Я хочу сделать каждую из этих папок объектом, чтобы позже я мог выполнить некоторую работу с файлами внутри них. Я пытаюсь использовать этот метод для возврата списка папок в виде объектов Book.

 public List<Book> getBooks(File folder){
    List<Book> books = new ArrayList<Book>();
    for (File f : folder.listFiles()){
        if (f.isDirectory()){
            System.out.println(f.getAbsolutePath()   ""   f.listFiles());
            books.add(new Book(f));
        }
    }
    return books;
}
  

Оператор println в этом блоке печатает, как и должно быть, прямой путь к папке, а затем адрес памяти вместе с некоторой другой информацией. Однако где-то в папке при вызове listFiles() выводится значение null. Папка, в которой это выполняется, не пуста. Затем эта предположительно пустая папка передается в метод инициализации моего класса.

 public Book(File bookFolder) {
    this.bookFolder = bookFolder;
    this.bookPath = bookFolder.getAbsolutePath();

    System.out.println(bookFolder   " "   bookFolder.listFiles());

    for (File f : bookFolder.listFiles()) {
        ...
    }
}
  

Оператор println в этом блоке выводит точно такой же путь к папке, а затем другой адрес памяти, который также ожидается. Когда он попадает в «пустую» папку, он снова выводит null для адреса памяти.

Теперь, что касается реальной проблемы, строка с циклом for — это то место, где программа завершает работу и выдает исключение NullPointerException, которое даже не описано в документации для метода listFiles.

Почему это может происходить? Кроме того, почему мои непустые папки возвращают значение null?

Комментарии:

1. Трассировки стека существуют не просто так. Прочитайте это, поймите.

2. @Mat — оператор ‘foreach’ ( : ) выдает NPE, если объект, по которому выполняется итерация, равен null (в вашем случае, bookFolder.listFiles() )

3. @skaffman — stacktrace сообщает вам только, где происходит NPE, а не почему. Иногда это очевидно, иногда нет, в зависимости от того, сколько происходит с этой строкой.

4. @Kevin K — спасибо, это был ответ, который я искал. Теперь мне просто нужно выяснить, почему они в первую очередь равны null.

5. В качестве дополнительного примечания, ваши имена переменных сбивают с толку. book Это File a, и чтобы добавить его в список books , необходимо создать a Book из a book . Я бы посоветовал не путать книги с файлами.

Ответ №1:

В документации к listFiles() методу четко указано, что он «Возвращает null, если это абстрактное имя пути не обозначает каталог, или если возникает ошибка ввода-вывода».

Одна из наиболее распространенных причин, по которой каталог не может быть указан, заключается в том, что процессу не хватает правильных разрешений. Вы запускаете это от своего имени или в какой-то службе, которая запускается от имени другого пользователя?

Кстати, File API — отличный пример того, насколько плохой может быть жизнь без исключений.

Комментарии:

1. Другой причиной может быть то, что файл не является каталогом.

2. Ну, в целом это, безусловно, верно! Но, в данном случае, похоже, что соответствующее тестирование выполнено, чтобы исключить это.

3. @erickson Я хотел знать, почему они возвращают null, когда я уверен, что они содержат другие файлы. Путь определенно является каталогом, поскольку я проверяю, чтобы убедиться, что это так, и другие папки на том же сервере нормально работают с этим кодом, поэтому я не думаю, что это проблема с разрешениями.

4. Этот код запускается службой, которая запускает его от имени администратора, что делает меня еще более уверенным, что это не проблема с разрешениями.

5. @erickson — Большое вам спасибо за вашу помощь. Как оказалось, мне, похоже, не хватает места, потому что я открываю так много файлов, похоже, именно поэтому listFiles () начинает возвращать null вместо адресов памяти.

Ответ №2:

Для разработчиков, которые уже включили следующие решения :

  1. Добавлено разрешение на хранение
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  

2. Каталог, из которого вы хотите перечислить файлы, существует.

  1. Включено разрешение на тестируемом устройстве в настройках разрешений приложения

ПРИВЕДЕННЫЙ НИЖЕ КОД РЕШИТ вашу ПРОБЛЕМУ, если SDK ВАШЕГО УСТРОЙСТВА БОЛЬШЕ ИЛИ РАВЕН ANDROID 10 (Q)

В файл манифеста включите этот код внутри тега

 <application android:requestLegacyExternalStorage="true"...</application>
  

Дайте мне знать, если ваша проблема решена!

Ответ №3:

У меня была аналогичная проблема с dir.listfiles(); возвращал null для папки пользователя AppData Local Microsoft Windows Temporary Internet Files Content.IE5

это была папка, для которой по умолчанию были установлены разрешения «все», запрещающие все

я думаю, что меня подкосил тот факт, что я никогда не ожидал, что там существует какое-либо разрешение Deny.

также для любого неясно, что я подразумеваю под разрешением запретить

когда вы устанавливаете «запретить» для пользовательских разрешений, это переопределяет «разрешить для пользовательских разрешений», если вы не удалите его, и это было при установке Windows 10 Home по умолчанию.

Ответ №4:

Для меня это было вызвано конечными пробелами. Используйте переменную.trim()