[✔️]cocos2dx的CCFileUtils深度理解

简介: [✔️]cocos2dx的CCFileUtils深度理解

重点看在Android上的实现


网络异常,图片无法展示
|


  • CCFileUtils-android.cpp


FileUtils* FileUtils::getInstance()
{
    if (s_sharedFileUtils == nullptr)
    {
        // Android的类
        s_sharedFileUtils = new FileUtilsAndroid();
    }
    return s_sharedFileUtils;
}


std::string FileUtils::fullPathForFilename(const std::string &filename) const{
    std::string fullpath;
    // 这个_searchPathArray里面就有assets这个很特殊的目录
    for (const auto& searchIt : _searchPathArray) {
        for (const auto& resolutionIt : _searchResolutionsOrderArray) {
            // 里面有平台代码,换取fullpath
            fullpath = this->getPathForFilename(newFilename, resolutionIt, searchIt);
            if (!fullpath.empty()) {
                // Using the filename passed in as key.
                _fullPathCache.emplace(name, fullpath);
                return fullpath;
            }
        }
    }
}
// 最终会来到这个函数
std::string FileUtils::getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const {
    // get directory+filename, safely adding '/' as necessary
    std::string ret = directory;
    if (directory.size() && directory[directory.size()-1] != '/'){
        ret += '/';
    }
    ret += filename;
    // if the file doesn't exist, return an empty string
    if (!isFileExistInternal(ret)) {
        ret = "";
    }
    return ret;
}


// 安卓平台判断文件是否是内置的资源
bool FileUtilsAndroid::isFileExistInternal(const std::string& strFilePath) const
{
    if (strFilePath.empty()) {
        return false;
    }
    bool bFound = false;
    // Check whether file exists in apk.
    if (strFilePath[0] != '/') {
        const char* s = strFilePath.c_str();
        // Found "assets/" at the beginning of the path and we don't want it
        // 注意这个_defaultResRootPath,它是一个protected变量,在init有赋值
        if (strFilePath.find(_defaultResRootPath) == 0) s += _defaultResRootPath.length();
        if (obbfile && obbfile->fileExists(s)) {
            bFound = true;
        }else if (FileUtilsAndroid::assetmanager){
            // 看到了Android平台的jni代码
            AAsset* aa = AAssetManager_open(FileUtilsAndroid::assetmanager, s, AASSET_MODE_UNKNOWN);
            if (aa){
                bFound = true;
                AAsset_close(aa);
            } else {
                // CCLOG("[AssetManager] ... in APK %s, found = false!", strFilePath.c_str());
            }
        }
    }
    else {
        FILE *fp = fopen(strFilePath.c_str(), "r");
        if (fp) {
            bFound = true;
            fclose(fp);
        }
    }
    return bFound;
}
#define  ASSETS_FOLDER_NAME          "assets/"
bool FileUtilsAndroid::init()
{
    _defaultResRootPath = ASSETS_FOLDER_NAME;
    // ...
}
void FileUtils::setSearchPaths(const std::vector<std::string>& searchPaths)
{
    // 每一次添加searchpaths的时候,都会检查rootPath的存在
    bool existDefaultRootPath = false;
    // ...
    if (!existDefaultRootPath) {
        _searchPathArray.push_back(_defaultResRootPath);
    }
}


安卓平台的搜索路径:


  • assets/src/


  • assets/res/


  • assets/


至此也就搞明白了,fullpath在Android上是一个假的路径


由于assets文件夹中的文件在APK文件中被打包,因此它们没有绝对路径。


string FileUtilsAndroid::getWritablePath() const
{
    // Fix for Nexus 10 (Android 4.2 multi-user environment)
    // the path is retrieved through Java Context.getCacheDir() method
    string dir("");
    string tmp = JniHelper::callStaticStringMethod("org/cocos2dx/lib/Cocos2dxHelper", "getCocos2dxWritablePath");
    if (tmp.length() > 0)
    {
        dir.append(tmp).append("/");
        return dir;
    }
    else
    {
        return "";
    }
}


public static String getCocos2dxWritablePath() {
    //赋值的逻辑: Cocos2dxHelper.sFileDirectory = activity.getFilesDir().getAbsolutePath();
    return Cocos2dxHelper.sFileDirectory;
}


Android的各种dir


目录方法 路径 特点和用途 卸载应用程序时是否会被删除
getDir() /data/data/包名/app_data/自定义目录名 应用程序的私有数据目录,通常用于存储应用程序的数据库文件或其他私有数据。可以指定自定义目录
getFilesDir() /data/data/包名/files 应用程序的私有文件目录,通常用于存储应用程序的数据文件。 固定目录
getCacheDir() /data/data/包名/cache 应用程序的私有缓存目录,通常用于存储临时文件或缓存数据。
getExternalFilesDir() /storage/emulated/0/Android/data/包名/files 应用程序在外部存储设备上的私有文件目录,通常用于存储需要与其他应用程序共享的数据文件。
getExternalCacheDir() /storage/emulated/0/Android/data/包名/cache 应用程序在外部存储设备上的缓存目录,通常用于存储临时文件或缓存数据。


目录
相关文章
|
JSON 小程序 数据格式
微信小程序的tabbar怎么配置
微信小程序的tabbar怎么配置
981 2
|
存储 移动开发 数据安全/隐私保护
高效反编译luac文件
高效反编译luac文件
|
监控 数据可视化 Java
visualvm工具远程对linux服务器上的JVM虚拟机进行监控与调优
本文档主要总结在window本地环境远程对linux服务断的JVM虚拟机进行监控与调优的方法。
447 0
深入分析luait反编译之luajit-decomp
#背景 Luajit在游戏中应用广泛,在逆向分析游戏过程中免不了与luajit打交道,那网上有非常多关于luajit反编译的资料,汇总起来常用的两种方案:https://github.com/zzwlpx/ljd 和 https://github.com/bobsayshilol/luajit-decomp, 第一种方案相对来说可读性好但兼容性差经常出现反编译异常崩溃。第二种方案反编译
8063 0
|
8月前
|
SQL JavaScript Unix
在线时间戳转换工具
免费在线时间戳转换工具,实时精准实现Unix时间戳与日期格式互转!
423 8
|
关系型数据库 MySQL 数据安全/隐私保护
mysql : 无法将“mysql”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查
mysql : 无法将“mysql”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查
mysql : 无法将“mysql”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查
|
Python
【Python3报错】Fatal error in launcher: Unable to create process using ……
【Python3报错】Fatal error in launcher: Unable to create process using ……
1450 1
|
存储 缓存 Java
createTempFile方法详解
createTempFile方法详解
|
Linux iOS开发 MacOS
Charles 抓包工具,支持抓取 exe 无需要额外设置,打开就能使用
Charles 抓包工具,支持抓取 exe 无需要额外设置,打开就能使用
663 0
|
Java Maven
idea编码GBK的不可映射字符Maven修改编码格式的多种方式
idea编码GBK的不可映射字符Maven修改编码格式的多种方式
1257 1