Java 文件存在且是目录,但 listFiles() 返回 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20714058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:46:24  来源:igfitidea点击:

File exists and IS directory, but listFiles() returns null

javaandroidfileiofile-permissions

提问by Wilson

The documentation for File.listFiles()suggests that nullwill ONLY be returned in the case that the file calling it is not a directory.

的文档File.listFiles()建议null只有在调用它的文件不是目录的情况下才会返回。

I have the following:

我有以下几点:

String dir = "/storage/emulated/0";
File f = new File(dir);
Log.v("Files",f.exists()+"");
Log.v("Files",f.isDirectory()+"");
Log.v("Files",f.listFiles()+"");

The log reads:

日志写道:

true
true
null

For some reason, listFiles() is returning nulleven though the Fileis recognized as a valid directory. I'm not super familiar with Android file hierarchy behavior, so I would guess the problem lies in there.

出于某种原因,listFiles() 正在返回,null即使File被识别为有效目录。我对 Android 文件层次结构的行为不是很熟悉,所以我猜问题出在那里。

For reference, I'm debugging on my Moto X, and results are the same whether the phone is plugged in to my computer or not - so I don't think it has to do with mounting when plugged in.

作为参考,我正在 Moto X 上进行调试,无论手机是否插入我的计算机,结果都是一样的 - 所以我认为这与插入时的安装无关。

采纳答案by BamsBamx

For those with this problem, add this to AndroidManifest.xml:

对于有此问题的人,请将其添加到 AndroidManifest.xml 中:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Problem solved :D

问题解决了:D

EDIT: If this does not work just make sure if path is correct

编辑:如果这不起作用,请确保路径是否正确

回答by msknapp

From the File 'listFiles' method documentation: Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.

来自 File 'listFiles' 方法文档:如果此抽象路径名不表示目录,或者发生 I/O 错误,则返回 null。

So perhaps an I/O error occurred. Check the permissions on that directory, does the user running the java program have the permission to read that directory? If not, there is your answer. If they do, then perhaps the directory is empty.

所以可能发生了 I/O 错误。检查该目录的权限,运行java程序的用户是否有读取该目录的权限?如果没有,那就有你的答案。如果他们这样做,那么目录可能是空的。

BTW you should not use +"" to convert something to a string, it's a bad practice since it's slower than String.valueOf. I would use apache's StringUtils to join that array into a string, but that requires adding that jar to your classpath.

顺便说一句,您不应该使用 +"" 将某些内容转换为字符串,这是一种不好的做法,因为它比 String.valueOf 慢。我会使用 apache 的 StringUtils 将该数组加入一个字符串中,但这需要将该 jar 添加到您的类路径中。

回答by thiagolr

My problem was that for some reason the android:sharedUserId="android.uid.system" attribute was not allowing the app to read /sdcard/ on a specific device.

我的问题是由于某种原因 android:sharedUserId="android.uid.system" 属性不允许应用程序在特定设备上读取 /sdcard/ 。

As I needed to do only a quick test, I removed the sharedUserId attribute, tested and added it back.

由于我只需要进行快速测试,因此我删除了 sharedUserId 属性,进行了测试并将其添加回来。

回答by kamal

Just add the permission in manifest uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" and your problem will be resolved.

只需在清单中添加权限uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" ,您的问题就会得到解决。

回答by Rajan Menon

In the manifest file at the <uses-permission .... >section, add this line android:name="android.permission.READ_EXTERNAL_STORAGE". I think this may solve your problem.

在该<uses-permission .... >部分的清单文件中,添加这一行android:name="android.permission.READ_EXTERNAL_STORAGE"。我认为这可能会解决您的问题。

回答by Ravi Joshi

For those with this problem you to give read permission, add this to AndroidManifest.xml:

对于有此问题的人,您要授予读取权限,请将其添加到 AndroidManifest.xml 中:

android:name="android.permission.READ_EXTERNAL_STORAGE" 

and you should also grant permission from

你还应该授予许可

Settings > Apps > "Your app name"> Permissions > storage

设置 > 应用程序 > “您的应用程序名称”> 权限 > 存储

回答by varotariya vajsi

For android version 23 or higher, you need to give run time permissionprogrammatically in onresume method as below,

对于 android 23 或更高版本,您需要在 onresume 方法中以编程方式授予运行时权限,如下所示,

public final String[] EXTERNAL_PERMS = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE
};

public final int EXTERNAL_REQUEST = 138;

requestForPermission();

public boolean requestForPermission() {

    boolean isPermissionOn = true;
    final int version = Build.VERSION.SDK_INT;
    if (version >= 23) {
        if (!canAccessExternalSd()) {
            isPermissionOn = false;
            requestPermissions(EXTERNAL_PERMS, EXTERNAL_REQUEST);
        }
    }

    return isPermissionOn;
}

public boolean canAccessExternalSd() {
    return (hasPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
}

private boolean hasPermission(String perm) {
    return (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, perm));

}

回答by Sam

I had a same problem in java but not in android where i am reading config file with path in quotes. I solved my issue with just removing quotes

我在 java 中有同样的问题,但在 android 中没有,我正在读取带引号的路径的配置文件。我通过删除引号解决了我的问题

So you can do it by String replace function or give it without quotes

所以你可以通过字符串替换函数来完成或者不带引号

String someString= "C:\path"; someString=someString.replace("\"","");

String someString="C:\path"; someString=someString.replace("\"","");

回答by tamo

In addition to other answers and comments, I'd suggest you check whether you need

除了其他答案和评论,我建议您检查是否需要

<application android:requestLegacyExternalStorage="true"

in your manifest. It seems that some recent apis need it.

在您的清单中。似乎最近的一些api需要它。

Anyway, zapl's commentis rather short but quite insightful. You can "ls -ld" the directory on the device (via "adb shell" or some other shells). If you have "r" permission on the directory, you can call listFiles(). Otherwise, it returns null. Note that you can access files under the unreadable directory if you know the file names and have "x" permission on the directory. You can know who you are by "whoami" and "groups" commands.

无论如何,zapl 的评论相当短,但很有见地。您可以“ls -ld”设备上的目录(通过“adb shell”或其他一些shell)。如果您对该目录具有“r”权限,则可以调用 listFiles()。否则,它返回 null。请注意,如果您知道文件名并且对该目录具有“x”权限,则您可以访问不可读目录下的文件。你可以通过“whoami”和“groups”命令知道你是谁。

回答by franke.wu

@tamo's answer resolved my issue, i compile exoplayer on ANQ, and set :

@tamo 的回答解决了我的问题,我在 ANQ 上编译 exoplayer,然后设置:

build.gradle :

构建.gradle:

android {
compileSdkVersion 29
buildToolsVersion '29.0.0'

defaultConfig {
    minSdkVersion 16
    targetSdkVersion 29
}

manifest.xml :

清单.xml :

  <application
  android:name="com.google.android.exoplayer.demo.ExoPlayerDemoApplication"
  android:label="@string/application_name"
  android:icon="@drawable/ic_launcher"
  android:largeHeap="true"
  android:allowBackup="false"
  android:requestLegacyExternalStorage="true">

i check android develop site, it's already explain this : https://developer.android.com/training/data-storage/compatibility

我检查了android开发站点,它已经解释了这一点:https: //developer.android.com/training/data-storage/compatibility

if you target API 29 or higher, just follow google's setting.

如果您的目标是 API 29 或更高版本,只需遵循 google 的设置。