计算文件夹大小的递归函数抛出 NullPointerException (Java)

发布于 2024-11-05 22:41:50 字数 806 浏览 4 评论 0原文

我编写了递归方法来计算文件夹大小:

    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:/ 上我得到了例外... 也许是因为我有隐藏的系统目录,我没有访问权限? 我们将不胜感激您的帮助。

I wrote recursive method to calculate folder size:

    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;
}

added additional checks as users advised. still getting NPE.

NPE occurs when executing:

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

on another folders it works fine. but on D:/ and C:/ i get the exception...
Maybe its because i have hidden system directories on which i have no access rights?
Your help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

若能看破又如何 2024-11-12 22:41:50

有人可能“同时”(即在递归期间)删除了该文件。

您可以添加一个测试,例如:

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

编辑 - 找到错误和解决方案

我可以复制它。当程序在回收站对象上循环时会崩溃。事实上,在这种情况下,dir.listFiles() 返回 null。

您需要像这样更新您的方法并且它可以工作:

        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);
            }
        }

Someone may have deleted the File 'in the mean time' (i.e., during recursivity).

You could add a test, something like:

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

EDIT - FOUND THE ERROR AND THE SOLUTION

I could replicate it. The program crashes when it loops on Recycle Bin objects. In fact, dir.listFiles() returns null in that case.

You need to update your method like this and it works:

        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);
            }
        }
如痴如狂 2024-11-12 22:41:50

我不同意其他人的观点,即 file 变量必须为 null。我不明白为什么 listFiles() 应该返回一个包含空条目的数组。相反,我认为 dir.listFiles() 本身会返回 null,如果在非目录文件上调用它,则会返回 null。因此,也许您应该尝试仅 if dir.isDirectory() 执行此操作,而现在您则执​​行 if (!dir.isFile())

更新

好的,将人们在此线程中的建议放在一起,这是一个片段,其中对多个不确定性进行了多个空检查。

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 会击中何处。

I don't agree with the others that it's the file variable that has to be null. I don't see why listFiles() should return an array which contains null entries. Rather, I think dir.listFiles() itself returns the null, which it does if it is called on a non-directory File. So perhaps you should try to do that only if dir.isDirectory(), whereas now you do it if (!dir.isFile()).

UPDATE

Ok, putting all together what the people have suggested in this thread, this is a snippet which has several null checks for the several uncertainties.

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;
}

See if this works for you, and if you are still interested, you can one remove one safety net at a time to see where the NPE hits.

情话墙 2024-11-12 22:41:50

可能是因为这些目录中没有文件,即您可能会在以下位置收到 NPE

for (File file : dir.listFiles()) {
            if (file.isFile()) //here NPE
                size += file.length();
            else
                size += calcSize(file);
        }

It might be because there is no files inside these directories ie you might be getting NPE at

for (File file : dir.listFiles()) {
            if (file.isFile()) //here NPE
                size += file.length();
            else
                size += calcSize(file);
        }
萌能量女王 2024-11-12 22:41:50

试试这个:

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

看看某个东西是否既不是文件也不是目录。

Try this:

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

And see if something is neither a file or a directory.

莳間冲淡了誓言ζ 2024-11-12 22:41:50

从 JDK listFiles() 返回

抽象路径名数组
表示文件和目录
该摘要表示的目录
路径名。数组将为空,如果
该目录是空的。返回空值
如果这个抽象路径名不
表示一个目录,或者如果出现 I/O 错误
发生。

在调用 listFiles() 之前检查 dir.exists() 和 dir.isDirectory() 是否存在,然后确保其不为 null。

From JDK listFiles() returns

An array of abstract pathnames
denoting the files and directories in
the directory denoted by this abstract
pathname. The array will be empty if
the directory is empty. Returns null
if this abstract pathname does not
denote a directory, or if an I/O error
occurs.

Check to see if dir.exists() and dir.isDirectory() before calling listFiles() and then ensure it is not null.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文