为什么File.listFiles在目录上调用时可以返回null?

Dan*_*ist 5 java android nullpointerexception file-listing

我正在创建一个Android应用程序,我想列出目录中的文件.我是通过打电话来做的

File[] files = path.listFiles(new CustomFileFilter());
Run Code Online (Sandbox Code Playgroud)

path是一个File通过调用创建的对象

File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
Run Code Online (Sandbox Code Playgroud)

当我然后files通过调用尝试获取数组的长度

int length = files.length;
Run Code Online (Sandbox Code Playgroud)

这行给了我一个NullPointerException,因为files是null.

我已经path通过调用检查了我是否尝试列出存在的文件

System.out.println("Path exists: " + path.exists());
Run Code Online (Sandbox Code Playgroud)

当我运行应用程序时,它会打印出来

Path exists: true
Run Code Online (Sandbox Code Playgroud)

在Android Studio控制台中,因此该目录存在.

我还打印了路径名称,即

/storage/emulated/0/Download
Run Code Online (Sandbox Code Playgroud)

所以这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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Sae*_*umi 7

将其添加到AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)

此权限允许您读取文件; 如果你不使用此许可,则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]);
        }
Run Code Online (Sandbox Code Playgroud)


sai*_*mar 5

确保您遵循了Saeed Masoumi \xe2\x80\x99s 的答案,如果您仍然遇到问题,那是因为您设置了 Target API 29 或更高版本。

\n\n

将此属性添加到清单文件的应用程序标记中,它将起作用。

\n\n
android:requestLegacyExternalStorage="true"\n
Run Code Online (Sandbox Code Playgroud)\n\n

根据google\xe2\x80\x99s 应用程序数据存储兼容性特征

\n\n

在您的应用与范围存储完全兼容之前,您可以使用以下方法之一暂时选择退出:

\n\n
    \n
  • 面向 Android 9(API 级别 28)或更低版本。
  • \n
  • 如果您的目标平台是 Android 10(API 级别 29)或更高版本,请在应用的清单文件中将 requestLegacyExternalStorage 的值设置为 true:
  • \n
\n\n
\n    <manifest ... >\n      <!-- This attribute is "false" by default on apps targeting\n           Android 10 or higher. -->\n        <application android:requestLegacyExternalStorage="true" ... >\n          ...\n        </application>\n    </manifest>\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

要测试面向 Android 9 或更低版本的应用在使用范围存储时的行为方式,您可以通过将 requestLegacyExternalStorage 的值设置为 false 来选择加入该行为。

\n