当在目录上调用File.listFiles时,为什么会返回null?

8

我正在创建一款Android应用,想要列出一个文件夹中的文件。我通过调用以下方法来实现:

File[] files = path.listFiles(new CustomFileFilter());

path 是一个 File 对象,可以通过调用相应的方法创建。

File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

当我尝试通过调用files数组的长度来获取其长度时,会出现以下情况。
int length = files.length;

这行代码抛出了一个NullPointerException异常,因为files是空的。

我已经通过调用以下代码检查了试图列出文件的路径 path 是否存在:

System.out.println("Path exists: " + path.exists());

当我运行该应用程序时,它会打印输出。
Path exists: true

在Android Studio控制台中,所以该目录存在。
我还打印了路径名,即
/storage/emulated/0/Download

所以path是一个目录,而不是文件。

我不知道为什么会出现NullPointerException,因为path是一个目录。

编辑CustomFileFilter类看起来像这样:

public class CustomFileFilter implements FileFilter {

    // Determine if the file should be accepted
    @Override
    public boolean accept(File file) {
        // If the file isn't a directory
        if(file.isDirectory()) {
            // Accept it
            return true;
        } else if(file.getName().endsWith("txt")) {
            // Accept it
            return true;
        }
        // Don't accept it
        return false;
    }
}

可能是由于CustomFileFilter类的原因,您在数组中没有获取到任何文件。请尝试使用path.listFiles()方法来运行相同的代码。 - ρяσѕρєя K
2
展示 path.isDirectory()path.canRead() 的输出。仅仅因为你说它是一个文件并不意味着它就是一个文件。 - chrylis -cautiouslyoptimistic-
如果没有匹配的文件,该方法将返回一个空数组,而不是null。 - chrylis -cautiouslyoptimistic-
1
@ρяσѕρєяK 我确实查看了Javadocs。请再次阅读它们。具体来说,请阅读它何时可以返回null的描述。这不是当您在目录中找不到任何文件时。 - chrylis -cautiouslyoptimistic-
根据Javadoc(http://docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles/),如果路径未被识别为目录,则listFiles()方法可能返回null。您可以检查path.isDirectory()吗? - Keen Sage
显示剩余5条评论
3个回答

9
将以下内容添加到AndroidManifest.xml文件中:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

此权限允许您读取文件;如果您不使用此权限,则 listFiles()list() 两者都将抛出 NullPointerException

以下是显示 /storage/emulated/0/Download 中所有文件的示例:

   String dir = "/storage/emulated/0/Download/";
        File f = new File(dir);
        String[] files = f.list();
        for(int i=0; i<files.length; i++){
            Log.d("tag", files[i]);
        }

不确定,但是如果用户没有读取权限,访问文件应该导致IOException而不是NullpointerException吧? - Keen Sage
@Sashwat 如果移除该权限,则会抛出 NullpointerException 异常。 - Saeed Masoumi

5

请确保你已经按照Saeed Masoumi的回答操作,如果仍然存在问题,则是因为你设置了目标API 29或更高版本。

在Manifest文件的application标签中添加此属性,它将正常工作。

android:requestLegacyExternalStorage="true"

根据Google的数据存储应用兼容性特性
在您的应用程序完全兼容作用域存储之前,您可以通过使用以下方法之一进行临时退出:
  • 目标为Android 9(API级别28)或更低版本。
  • 如果您的目标是Android 10(API级别29)或更高版本,请在应用程序的清单文件中将requestLegacyExternalStorage的值设置为true:

    <manifest ... >
      <!-- This attribute is "false" by default on apps targeting
           Android 10 or higher. -->
        <application android:requestLegacyExternalStorage="true" ... >
          ...
        </application>
    </manifest>

为了测试针对 Android 9 或更低版本的应用在使用作用域存储时的行为,您可以通过将 requestLegacyExternalStorage 的值设置为 false 来选择加入该行为。


我曾陷入了麻烦之中,这帮了我很大的忙……非常感谢你。 - Abdullah Programmer

3

对于那些使用Android SDK>23的人,您需要通过代码授予权限:

可以使用以下内容:

 boolean grantedAll = ContextCompat.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (!grantedAll)
   {
     ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_PERMISSIONS);
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接