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

计算文件夹大小的递归函数抛出NullPointerException(Java),java,recursion,io,nullpointerexception,Java,Recursion,Io,Nullpointerexception,我编写了递归方法来计算文件夹大小: private static long calcSize(File dir) { if (dir.isFile() && dir.canRead()) { return dir.length(); } long size = 0; if ( dir.exists() && dir.isDirectory() && dir.canRead()) {

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

    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:/上,我得到了一个例外。。。 可能是因为我有隐藏的系统目录,我没有访问权限?
非常感谢您的帮助。

这可能是因为这些目录中没有文件,即您可能正在获取NPE

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

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

然后查看某个内容是否既不是文件也不是目录。

可能有人“同时”(即在递归过程中)删除了该文件

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

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

我不同意其他人的观点,即
文件
变量必须为
null
。我不明白为什么
listFiles()
应该返回一个包含空条目的数组。相反,我认为
dir.listFiles()
本身返回空值,如果在非目录
文件
上调用它就会返回空值。因此,如果dir.isDirectory(),那么您可能应该尝试只执行
操作,而现在如果(!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的位置。

来自JDK
listFiles()
返回

抽象路径名数组 表示中的文件和目录 此摘要表示的目录 路径名。如果 目录为空。返回空值 如果此抽象路径名不存在 表示目录,或者如果出现I/O错误 发生


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

当某个引用为null时,会出现null指针异常,并且仍然使用它。查看该程序2秒钟可以清楚地看出,只有值file或listFiles()的retrun值可以为null。你应该检查一下。你有这台机器的管理员权限吗?可能是您要求在您没有权限的目录上列出文件。只是猜测一下。MeBigFatGuy,也许你是对的,我有管理员权限,但仍有名为“系统卷信息”和“$RECYCLE.BIN”的隐藏文件夹,我对此没有权限。从文档:返回:一个抽象路径名数组,表示此抽象路径名表示的目录中的文件和目录。如果目录为空,则数组将为空。如果此抽象路径名不表示目录,或者发生I/O错误,则返回null。我编辑了代码以显示从何处获取异常,我在空文件夹上检查了异常,并且在空文件夹上正常工作。在同一行仍然存在异常,看起来有空目录。。。或者类似的东西?我在同一行添加了这个检查仍然是NPE。@如果发生i/O错误,taypen-listFiles()也可能返回null。权限的缺乏可能表现为I/O错误,返回空数组。基本上,您应该处理listFiles()返回空数组的问题。他可以检查listFiles是否不返回空数组。顺便说一句,@taypen,披露NPE发生的行号如何?正确。来自JDK“一个抽象路径名数组,表示此抽象路径名表示的目录中的文件和目录。如果目录为空,则该数组为空。如果此抽象路径名不表示目录,或者如果发生I/O错误,则返回null。”