使用AssetManager.list()方法列出子目录中的资产列表。

50

我的应用程序有一个资产目录,其中我已经倾泻了一堆我需要在运行时加载的文本文件。

我有一个特定类型的资产目录(即“assets/subdir”),我想逐个加载该目录中的所有文件。

我有这样的代码:


AssetManager assetMgr = getAssets();

String[] assetsIWant = assetMgr.list("subdir");

for(String asset: assetsIWant) {
  doAssetyThing(asset);
}
我尝试了无数种参数来调用assetMgr.list()方法,但是仍然没有得到想要的结果。 如果我使用“/”,则会返回一个包含“assets”目录和一些随机其他项目(例如META_INF)的列表。 如果我传递任何其他字符串(如“assets”或“assets /”或“/ assets”或“/ assets /”或“mysubdir”或“/ mysubdir”或“assets / mysubdir”等),那么我会收到一个空数组。 不幸的是,文档非常不连贯。 有人知道list()参数的正确公式吗?
10个回答

36

对我来说,传递一个空字符串似乎是有效的。 当我执行以下操作时,我会得到我的资源目录中文件的列表:

AssetManager aMan = appContext.getAssets();
String[] filelist = aMan.list("");

29

我用以下代码列出了assets/myFolder/中的文件名:

String[] fileNames =getAssets().list("myFolder");
for(String name:fileNames){
     System.out.println(name);    
}
注意方法列表中的参数不包含“/”符号。

18

如果你需要访问层次结构中更深层的文件夹,请使用

String[] fileNames =getAssets().list("myFolder"+File.separator+"mysubfolder");

使用字符串内部的“/”将导致结果为空的字符串数组。


13

我不确定为什么会这样,但当我列出“ / ”时,我得到的是根级别的内容,而不是来自我的“assets”目录的内容。在我花费的短时间内,我实际上找不到正确地列出我的资产文件夹的方法。

我使用的解决方法是在我的"assets"目录中创建一个"subdir"子目录。我将所有我想要访问的资产放在这个"subdir"中,然后执行以下操作:

String[] assetsIWant = assetMgr.list("subdir");

我不知道为什么“/”会将“assets”目录本身列为其中的一个文件,但是在给list指定路径时,您不必指定“assets”目录。也许其他人知道,但我希望这个提示能对你有所帮助。


3
"/"指向您的应用程序根文件夹。"."指向当前(资产)文件夹。 - Coyote

8
这个主题有很多类似的问题,我怀疑你正在使用库项目中的资产文件夹。如果你尝试在Android库项目中访问资产,你将得到空内容和你在这里描述的确切症状。
来自Android“项目”文档
来源:http://developer.android.com/tools/projects/index.html 引用: 库项目不能包含原始资产 工具不支持在库项目中使用原始资产文件(保存在资产/目录中)。应用程序使用的任何资源都必须存储在应用程序项目本身的资产/目录中。但是,保存在res/目录中的资源文件是受支持的。
如果是这种情况,答案是你应该只在应用程序项目的资产文件夹中包含原始资产,而不是在任何标记为库的项目中(你可以通过右键单击项目并选择属性,选择左侧的android条目,并查看是否是library复选框来检查)。

4
假设您设置了这个文件夹:Assets->SubDir1。 在Subdir1中有一些文件,如A.txtB.txtC.txt。 因此从项目的目录中,它将是Assets/SubDir1/A.txt
考虑到这一点,访问该文件的方式与您所做的类似,只需要添加一件事。那就是在doAssetyThing函数中。您必须在其前面放置SubDir1目录,即使您在.list("");中进行了"SubDir1"的过滤。
例如:
    AssetManager am = getResources().getAssets();
    String [] list = am.list("SubDir1");
    for (String s:list) {
        doAssetyThing("SubDir1/" + s);

        //I use this next line as the start of copying a pdf from one location
        //to another. I wanted to give you a real function in use.

        InputStream inStream = am.open("SubDir1/" + s);

        //more code
    }

我希望这很清楚并能对您有所帮助!

2

我使用以下两种方法来确保所需资产存在:

    protected boolean hasAsset(String id) {
    return hasAsset(id,"");
}

protected boolean hasAsset(String id, String dir) {
    int idx = id.indexOf('/');
    if (idx > 0 && idx < id.length() - 1) {
        if (dir.length() > 0) {
            dir = dir + "/" + id.substring(0,idx);
        } else
            dir = id.substring(0,idx);
        return hasAsset(id.substring(idx + 1), dir);
    }
    try {
        return Arrays.asList(context.getAssets().list(dir)).contains(id);
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

2

由于某些原因,空目录不会列出。

至少在我的经验中,它们没有被列出。

也就是说,如果您在资源区域有some-dir/d1/f1和some-dir/d2,并且您列出(“some-dir”),则d2不会被列出。


1
这个解决方案对我来说似乎有效: 在assets目录下保留每个要从子目录访问的文件的副本。 使用相同的约定。即list("subdirectory") 它不会读取assets文件夹中的文件,但会读取其子目录中所有“复制”的文件。 很奇怪!但是有效!

0
这里是使用Kotlin的解决方案:
val assetManager = context.resources.assets
assetManager
    .list("myDirectoryNameInAssetsFolder")
    .also { Log.i("Meow", "Detected files: ${it?.joinToString()}") }
    ?.map { "myDirectoryNameInAssetsFolder/$it" }
    ?.map(assetManager::open)
    ?.map { it.bufferedReader().use(BufferedReader::readText) }
    ?.also { Log.i("Meow", "Text of each file:") }
    ?.forEach { fileText -> Log.i("Meow", fileText) }
    ?: error("Could not access/read files in assets folder")

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