40

我正在尝试从本机端访问资产文件夹中的图像文件。现在,我可以成功搜索 assets 文件夹及其子目录,找到我要查找的特定文件:

AAssetDir* assetDir = AAssetManager_openDir(asset_manager, "images");
const char* filename;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL)
{
   __android_log_print(ANDROID_LOG_DEBUG, "Debug", filename);
}

AAssetDir_close(assetDir);

我也在使用 OSG。我使用以下代码将图像设置为我的着色器的纹理:

texture->setImage(osgDB::readImageFile(fileNameWithPath));

但该文件名也必须包含绝对路径,因为它不在同一目录中。但是我发现我无法获得资产目录的绝对路径,因为它是与 APK 一起压缩的。

由于我无法访问绝对路径,我还能用什么其他方式来获取图像?另请注意,我确实希望将资产文件夹中的文件与 sd 卡保持一致。

4

2 回答 2

38

AAssetManager_open您可以使用&从资产中读取图像AAsset_read,但由于资产位于 apk 中,您无法获得它的文件路径名 - 它也在那里被压缩。您可以将数据保存到文件并稍后从该文件中读取,或者如果 OSG 允许,您可以直接处理从资产文件中获得的块。

这里

AAssetDir* assetDir = AAssetManager_openDir(mgr, "");
const char* filename = (const char*)NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
    AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
    char buf[BUFSIZ];
    int nb_read = 0;
    FILE* out = fopen(filename, "w");
    while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0)
        fwrite(buf, nb_read, 1, out);
    fclose(out);
    AAsset_close(asset);
}
AAssetDir_close(assetDir);
于 2012-11-09T23:43:15.353 回答
1

还有一点值得一提的是,android 将可以一次读取的资产大小限制为 1Mb。如果你的文件比那个大,你必须把它分成块。这是我的工作解决方案,它将文件分块加载到字符向量:

AAssetManager * mgr = app->activity->assetManager; 
AAssetDir* assetDir = AAssetManager_openDir(mgr, "");

const char* filename;
std::vector<char> buffer;

while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) 
{
    //search for desired file
    if(!strcmp(filename, /* searched file name */)) 
    {
        AAsset *asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);

        //holds size of searched file
        off64_t length = AAsset_getLength64(asset);
        //keeps track of remaining bytes to read
        off64_t remaining = AAsset_getRemainingLength64(asset);
        size_t Mb = 1000 *1024; // 1Mb is maximum chunk size for compressed assets
        size_t currChunk;
        buffer.reserve(length);

        //while we have still some data to read
        while (remaining != 0) 
        {
            //set proper size for our next chunk
            if(remaining >= Mb)
            {
                currChunk = Mb;
            }
            else
            {
                currChunk = remaining;
            }
            char chunk[currChunk];

            //read data chunk
            if(AAsset_read(asset, chunk, currChunk) > 0) // returns less than 0 on error
            {
                //and append it to our vector
                buffer.insert(buffer.end(),chunk, chunk + currChunk);
                remaining = AAsset_getRemainingLength64(asset);
            }
        }
        AAsset_close(asset);
    }

}
于 2016-12-02T15:10:53.630 回答