Рекурсивная функция, которая вычисляет размер папки, генерирует исключение NullPointerException (Java) - PullRequest
1 голос
/ 10 мая 2011

Я написал рекурсивный метод для расчета размера папки:

    private static long calcSize(File dir) {
    if (dir.isFile() && dir.canRead()) {
        return dir.length();
    }
    long size = 0;
    if ( dir.exists() && dir.isDirectory() && dir.canRead()) {
        for (File file : dir.listFiles()) { //Here NPE
            if (file.isFile()  && dir.canRead())
                size += file.length();
            else if (file.isDirectory())
                size += calcSize(file);
            else
                throw new Error("What is this: " + file);
        }
    }
    return size;
}

добавлены дополнительные проверки, как советовали пользователи. все еще получаю NPE.

NPE возникает при выполнении:

calcSize(new File("D:/"))

на других папках работает нормально. но на D: / и C: / я получаю исключение ... Может быть потому, что у меня есть скрытые системные каталоги, к которым у меня нет прав доступа? Ваша помощь будет оценена.

Ответы [ 5 ]

1 голос
/ 10 мая 2011

Я не согласен с остальными, что переменная file должна быть null. Я не понимаю, почему listFiles() должен возвращать массив, который содержит нулевые записи. Скорее, я думаю, что dir.listFiles() само возвращает ноль, что и происходит, если он вызывается не в каталоге File. Так что, возможно, вы должны попытаться сделать это только if dir.isDirectory(), тогда как сейчас вы делаете это if (!dir.isFile()).

UPDATE

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

private static long calcSize(File dir) {
    if (dir == null) return 0;
    if (dir.isFile()) return dir.length();
    if (!dir.isDirectory()) return 0;

    File[] files = dir.listFiles();
    if (files == null) return 0;

    long size = 0;
    for (File file : files) {
        if (file == null) continue;
        if (file.isFile())
            size += file.length();
        else
            size += calcSize(file);
    }

    return size;
}

Посмотрите, работает ли это для вас, и если вы все еще заинтересованы, вы можете удалить одну страховочную сетку за раз, чтобы увидеть, куда попадает NPE.

1 голос
/ 10 мая 2011

Кто-то, возможно, удалил файл «за среднее время» (т.е. во время рекурсивности).

Вы можете добавить тест, что-то вроде:

if ( dir.exists() ) {
   ...
}

РЕДАКТИРОВАТЬ - НАЙТИ ОШИБКУ И РЕШЕНИЕ

Я мог бы повторить это. Программа вылетает, когда зацикливается на объектах корзины. Фактически, dir.listFiles () возвращает ноль в этом случае.

Вам нужно обновить ваш метод следующим образом, и он работает:

        long size = 0;
        System.out.println(dir.toString());
        File[] tmp = dir.listFiles();
        if ( tmp != null ) {
            for (File file : dir.listFiles()) { // NPE gone
                if (file.isFile())
                    size += file.length();
                else
                    size += calcSize(file);
            }
        }
0 голосов
/ 10 мая 2011

От JDK listFiles() возвращает

Массив абстрактных путей обозначает файлы и каталоги в каталог, обозначенный этим рефератом путь к файлу. Массив будет пустым, если каталог пуст. Возвращает ноль если этот абстрактный путь не обозначить каталог, или если ошибка ввода-вывода происходит.

Проверьте, проверяют ли dir.exists () и dir.isDirectory () перед вызовом listFiles (), а затем убедитесь, что оно не равно нулю.

0 голосов
/ 10 мая 2011

Попробуйте это:

if (file.isFile())
    size += file.length();
else if (file.isDirectory())
    size += calcSize(file);
else
    throw new Error("What is this: " + file);

И посмотрите, не является ли что-то ни файлом, ни каталогом.

0 голосов
/ 10 мая 2011

Это может быть связано с тем, что в этих каталогах нет файлов, т.е. вы можете получить NPE на

for (File file : dir.listFiles()) {
            if (file.isFile()) //here NPE
                size += file.length();
            else
                size += calcSize(file);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...