为什么在目录上调用时 File.listFiles return 可以为空?
Why can File.listFiles return null when called on a directory?
我正在创建一个 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
class 看起来像这样:
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;
}
}
将此添加到 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]);
}
正在开发androidSDK>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);
}
确保你遵循了 的回答,如果你仍然遇到问题,那是因为你设置了目标 API 29 或更高。
将此 属性 添加到您的 Manifest 文件的应用程序标签中,它将起作用。
android:requestLegacyExternalStorage="true"
根据google’s App compatibility features for data storage:
在您的应用与分区存储完全兼容之前,您可以使用以下方法之一暂时选择退出:
- 目标 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 来选择加入该行为。
我正在创建一个 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
class 看起来像这样:
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;
}
}
将此添加到 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]);
}
正在开发androidSDK>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);
}
确保你遵循了
将此 属性 添加到您的 Manifest 文件的应用程序标签中,它将起作用。
android:requestLegacyExternalStorage="true"
根据google’s App compatibility features for data storage:
在您的应用与分区存储完全兼容之前,您可以使用以下方法之一暂时选择退出:
- 目标 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 来选择加入该行为。