使用 AssetManager.list() 列出子目录中的资源

问题描述 投票:0回答:10

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

我有一个充满特定类型资产的目录(即“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() 参数的正确公式是什么吗?

java android android-assets android-assetmanager
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"
目录中的东西。实际上,我在尝试的短时间内没有找到正确列出我的资产文件夹的方法。

我使用的解决方法是在我的

"subdir"
目录中创建一个
"assets"
目录。我把我想要访问的所有资源都放在这个
"subdir"
中,然后执行:

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

我不知道为什么

"/"
"assets"
目录本身列为其文件之一,但在为
"assets"
提供路径时不必指定
list
目录。也许其他人知道,但我希望这个技巧无论如何都能帮助你。


8
投票

围绕这个主题有很多类似的问题,我怀疑您正在库项目中使用资产文件夹。如果您尝试访问 Android 上的库项目中的资源,您将得到空内容以及您在此处描述的确切症状

来自android“项目”文档

来源:http://developer.android.com/tools/projects/index.html

图书馆项目不能包含原始资产

该工具不支持使用原始资源文件(保存在assets/目录中) 一个图书馆项目。应用程序使用的任何资产资源都必须是 存储在应用程序项目本身的assets/目录中。 但是,支持保存在 res/ 目录中的资源文件。

如果是这种情况,答案是您应该只在应用程序项目的资产文件夹中包含原始资源在任何标记为库的项目中(您可以通过右键单击项目并选择属性来检查这一点,然后选择左侧的 android 条目并查看 is 库复选框)


4
投票

假设您设置了此文件夹:

Assets->SubDir1
。您在
Subdir1
中拥有诸如
A.txt
B.txt
C.txt
之类的东西。因此,从项目目录来看,它将是
Assets/SubDir1/A.txt

考虑到这一点,访问该文件的方式与您正在做的类似,只是添加了一件事。那一件事就在你的

doAssetyThing
函数中。你必须把
SubDir1
目录放在它前面,即使你在
"SubDir1"
中做了
.list("");

的过滤

示例:

    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
投票

这个解决方案似乎对我有用: 也保留要从资产目录中的子目录访问的每个文件的副本。 使用相同的约定。即

list("subdirectory")

它不会读取assets文件夹中的文件,而是读取其子目录中的所有“复制”文件。 诡异的!!但有效!


0
投票

这是使用 Kotlin 的解决方案:

context
    .resources
    .assets
    .list("myDirectoryNameInAssetsFolder")
    .also { Log.i("Meow", "Detected files: ${it?.joinToString()}") }
    ?.map(::Path)
    // Now, use the list of Paths
    ?.map { it.bufferedReader().use(BufferedReader::readText) }
    .also { Log.i("Meow", "Text of each file:") }
    ?.forEach { fileText -> Log.i("Meow", fileText) }
    ?: error("Could not read files in assets folder")
© www.soinside.com 2019 - 2024. All rights reserved.