cocos2dx-2.x CCFileUtils文件管理类分析(2)

在1中,我只是针对整体结构进行了分析,那么在2中,我将会对一些我们常用的函数进行分析。

    //获取给定文件名的全路径
    //下面这很长一段注释,通过举例子,像我们说明cocos2dx获取文件全路径的规则。
    //这段我就不翻译了,直接通过代码来看。
    /** Returns the fullpath for a given filename.

     First it will try to get a new filename from the "filenameLookup" dictionary.
     If a new filename can't be found on the dictionary, it will use the original filename.
     Then it will try to obtain the full path of the filename using the CCFileUtils search rules: resolutions, and search paths.
     The file search is based on the array element order of search paths and resolution directories.

     For instance:

     	We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths,
     	and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd")
     	to resolutions vector by setSearchResolutionsOrder. The "internal_dir" is relative to "Resources/".

		If we have a file named 'sprite.png', the mapping in fileLookup dictionary contains `key: sprite.png -> value: sprite.pvr.gz`.
     	Firstly, it will replace 'sprite.png' with 'sprite.pvr.gz', then searching the file sprite.pvr.gz as follows:

     	    /mnt/sdcard/resources-ipadhd/sprite.pvr.gz      (if not found, search next)
     	    /mnt/sdcard/resources-ipad/sprite.pvr.gz        (if not found, search next)
     	    /mnt/sdcard/resources-iphonehd/sprite.pvr.gz    (if not found, search next)
     	    /mnt/sdcard/sprite.pvr.gz                       (if not found, search next)
     	    internal_dir/resources-ipadhd/sprite.pvr.gz     (if not found, search next)
     	    internal_dir/resources-ipad/sprite.pvr.gz       (if not found, search next)
     	    internal_dir/resources-iphonehd/sprite.pvr.gz   (if not found, search next)
     	    internal_dir/sprite.pvr.gz                      (if not found, return "sprite.png")

        If the filename contains relative path like "gamescene/uilayer/sprite.png",
        and the mapping in fileLookup dictionary contains `key: gamescene/uilayer/sprite.png -> value: gamescene/uilayer/sprite.pvr.gz`.
        The file search order will be:

     	    /mnt/sdcard/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz      (if not found, search next)
     	    /mnt/sdcard/gamescene/uilayer/resources-ipad/sprite.pvr.gz        (if not found, search next)
     	    /mnt/sdcard/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz    (if not found, search next)
     	    /mnt/sdcard/gamescene/uilayer/sprite.pvr.gz                       (if not found, search next)
     	    internal_dir/gamescene/uilayer/resources-ipadhd/sprite.pvr.gz     (if not found, search next)
     	    internal_dir/gamescene/uilayer/resources-ipad/sprite.pvr.gz       (if not found, search next)
     	    internal_dir/gamescene/uilayer/resources-iphonehd/sprite.pvr.gz   (if not found, search next)
     	    internal_dir/gamescene/uilayer/sprite.pvr.gz                      (if not found, return "gamescene/uilayer/sprite.png")

     If the new file can't be found on the file system, it will return the parameter pszFileName directly.

     @since v2.1
     */
    virtual std::string fullPathForFilename(const char* pszFileName);

    -->>
    std::string CCFileUtils::fullPathForFilename(const char* pszFileName)
{
    CCAssert(pszFileName != NULL, "CCFileUtils: Invalid path");

    //判断是否是绝对路径,如果是绝对路径就直接返回。
    /*
        //android下 判断依据就是是否以'/'开头或者以assets/开头。下面这个函数,注释的很清楚。
	//你可以做个实验:
	//例: Get data from file(/second_bg.png) failed! 我在创建精灵时传递/second_bg.png路径
	bool CCFileUtilsAndroid::isAbsolutePath(const std::string& strPath)
	{
	    // On Android, there are two situations for full path.
	    // 1) Files in APK, e.g. assets/path/path/file.png
	    // 2) Files not in APK, e.g. /data/data/org.cocos2dx.hellocpp/cache/path/path/file.png, or /sdcard/path/path/file.png.
	    // So these two situations need to be checked on Android.
	    if (strPath[0] == '/' || strPath.find(m_strDefaultResRootPath) == 0)
	    {
		return true;
	    }
	    return false;
	}
    */
    std::string strFileName = pszFileName;
    if (isAbsolutePath(pszFileName))
    {
        //CCLOG("Return absolute path( %s ) directly.", pszFileName);
        return pszFileName;
    }

    // Already Cached ?
    //是否已经缓存,如果缓存过,直接返回
    std::map<std::string, std::string>::iterator cacheIter = m_fullPathCache.find(pszFileName);
    if (cacheIter != m_fullPathCache.end())
    {
        //CCLOG("Return full path from cache: %s", cacheIter->second.c_str());
        return cacheIter->second;
    }

    /*
	std::string CCFileUtils::getNewFilename(const char* pszFileName)
	{
	    const char* pszNewFileName = NULL;
	    // in Lookup Filename dictionary ?
	    //可以把这个m_pFilenameLookupDict(默认为NULL)字典理解为一种查找
	    //比如这个字典里存了一个"fish.png(key)" --> "big_fish.png(value)"
	    //那么我们传入fish.png是,就会给我们转化为big_fish.png。如果没有,则返回我们传入的。
	    CCString* fileNameFound = m_pFilenameLookupDict ? (CCString*)m_pFilenameLookupDict->objectForKey(pszFileName) : NULL;
	    if( NULL == fileNameFound || fileNameFound->length() == 0) {
		pszNewFileName = pszFileName;
	    }
	    else {
		pszNewFileName = fileNameFound->getCString();
		//CCLOG("FOUND NEW FILE NAME: %s.", pszNewFileName);
	    }
	    return pszNewFileName;
	}
    */
    // Get the new file name.
    std::string newFilename = getNewFilename(pszFileName);

    string fullpath = "";

    //下面这一段很关键:
    //m_searchPathArray 前面介绍过搜索路径数组,需要我们手动设置。android的初始话会添加一个默认值为
    //m_searchPathArray.push_back(m_strDefaultResRootPath)即,"assets/"。

    /* m_searchResolutionsOrderArray 可以理解为分辨率搜索顺序,就按开头注释说明的那样
        //m_searchPathArray
	We set two elements("/mnt/sdcard/", "internal_dir/") to search paths vector by setSearchPaths,

	//m_searchResolutionsOrderArray
     	and set three elements("resources-ipadhd/", "resources-ipad/", "resources-iphonehd")
     	to resolutions vector by setSearchResolutionsOrder. 

        //组合后的路径
	/mnt/sdcard/resources-ipadhd/sprite.pvr.gz      (if not found, search next)
     	/mnt/sdcard/resources-ipad/sprite.pvr.gz        (if not found, search next)
     	/mnt/sdcard/resources-iphonehd/sprite.pvr.gz    (if not found, search next)

	总结:从这里可以看出,m_searchPathArray在前面的路径,会优先搜索,m_searchResolutionsOrderArray也一样。
    */
    for (std::vector<std::string>::iterator searchPathsIter = m_searchPathArray.begin();
         searchPathsIter != m_searchPathArray.end(); ++searchPathsIter) {
        for (std::vector<std::string>::iterator resOrderIter = m_searchResolutionsOrderArray.begin();
             resOrderIter != m_searchResolutionsOrderArray.end(); ++resOrderIter) {

            //CCLOG("\n\nSEARCHING: %s, %s, %s", newFilename.c_str(), resOrderIter->c_str(), searchPathsIter->c_str());

	    //下面我分析一下这个函数:-->> 2
            fullpath = this->getPathForFilename(newFilename, *resOrderIter, *searchPathsIter);

	    //这里会对找到的路径,进行缓存
            if (fullpath.length() > 0)
            {
                // Using the filename passed in as key.
                m_fullPathCache.insert(std::pair<std::string, std::string>(pszFileName, fullpath));
                //CCLOG("Returning path: %s", fullpath.c_str());
                return fullpath;
            }
        }
    }

    //CCLOG("cocos2d: fullPathForFilename: No file found at %s. Possible missing file.", pszFileName);

    // The file wasn't found, return the file name passed in.
    return pszFileName;
}

--> 2
//filename -- 传入的文件名
//searchPath -- 搜索路径
//resolutionDirectory -- 资源分辨率路径
std::string CCFileUtils::getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath)
{
    std::string file = filename;
    std::string file_path = "";
    size_t pos = filename.find_last_of("/");
    if (pos != std::string::npos)
    {
        file_path = filename.substr(0, pos+1);
        file = filename.substr(pos+1);
    }

    //如果传入的"gamescene/uilayer/sprite.png"是这样的路径,那么进行一定的处理,
    //处理成:path = searchPath + gamescene/uilayer/ + resourceDirectory
              file = sprite.png
    ///mnt/sdcard/ gamescene/uilayer/ resources-ipadhd/sprite.pvr.gz
    // searchPath + file_path + resourceDirectory
    std::string path = searchPath;
    path += file_path;
    path += resolutionDirectory;

    path = getFullPathForDirectoryAndFilename(path, file);

    //CCLOG("getPathForFilename, fullPath = %s", path.c_str());
    return path;
}

-->>
std::string CCFileUtils::getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename)
{
    std::string ret = strDirectory+strFilename;
    //如果文件存在,就把文件的路径返回,这个路径可能是绝对路径,也可能是包里的路径
    if (!isFileExist(ret)) {
        ret = "";
    }
    return ret;
}

-->>

//把上面合成的整个文件路径传进去,判断文件是否存在
bool CCFileUtilsAndroid::isFileExist(const std::string& strFilePath)
{
    if (0 == strFilePath.length())
    {
        return false;
    }

    bool bFound = false;

    // Check whether file exists in apk.
    //如果不是以'/'开头,就在android包里查找
    if (strFilePath[0] != '/')
    {
	//如果不是以"assets/"开头,则插入
        std::string strPath = strFilePath;
        if (strPath.find(m_strDefaultResRootPath) != 0)
        {// Didn't find "assets/" at the beginning of the path, adding it.
            strPath.insert(0, m_strDefaultResRootPath);
        }

	//在安装包里查找,看是否存在
        if (s_pZipFile->fileExists(strPath))
        {
            bFound = true;
        }
    }
    else
    {
        //如果是绝对路径,看否打开成功,如果成功,则证明文件存在。
        FILE *fp = fopen(strFilePath.c_str(), "r");
        if(fp)
        {
            bFound = true;
            fclose(fp);
        }
    }
    return bFound;
}

总结:这里需要知道一点,就是先加载搜索路径的路径,会优先搜索到。
      比如热更新,我们只要把更新路径设置在前面即可。

时间: 2024-10-23 06:03:11

cocos2dx-2.x CCFileUtils文件管理类分析(2)的相关文章

cocos2d-x v3.2 FlappyBird 各个类对象具体代码分析(7)

今天我们介绍最后两个类 GameOverLayer类 GameLayer类 GameLayer类是整个游戏中最重要的类,因为是整个游戏的中央系统,控制着各个类(层)之间的交互,这个类中实现了猪脚小鸟和它的敌人(管道和草地- . -)碰撞检测,说道物理引擎的碰撞检测,我也是第一次接触,也没多大难度,就直接调用了cocos2d-x的接口,这个类就是游戏的主场景,游戏就是在这里进行的. GameOverLayer类,游戏结束后一些分数的显示,还有就是奖牌的实现(楼主写的很简单......),这边比较有

linux基础入门之文件管理类命令

文件管理类命令 命令和选项 command [options] [arguments] 命令      选项    参数 选项 短选项-   例(-h -l -a) 短选项可组合 例(-hla) 有些命令短选项可以不带-, 通常称作BSD风格的选项 例(ps aux ,tar xf) 有些选项需要带参数 tail -n 2 /etc/passwd 长选项不能组合 --help --list 如果需要参数 长选项的参数通常需要=号  --size=1G 命令后的参数就是命令的作用对象 例:ls /

cocos2dx骨骼动画Armature源码分析(三)

代码目录结构 cocos2dx里骨骼动画代码在cocos -> editor-support -> cocostudio文件夹中,win下通过筛选器,文件结构如下.(mac下没有分,是整个一坨) armature(目录): animation(目录):动画控制相关. CCProcessBase(文件): ProcessBase(类):CCTween和ArmatureAnimation的基类. CCTWeen(文件): Tween(类):控制flash里一个layer的动画. CCArmatur

linux下部分文件管理类基本命令汇总以及bash展开特性介绍

一.文件管理类基本命令 1.1.表格汇总 今天要讲解的命令如下表所示,按照外部命令和内建命令做基本划分: 内建命令列表: 命令名字 基本说明 file 检测文件类型 cd 改变shell的工作目录 dirs 显示目录堆栈信息 popd 从堆栈中移除目录 pushd 向堆栈中添加目录 外部命令列表: 命令名字 基本说明 ls 列出目录内容 tree 以"树状"格式列出目录内容 pwd 打印当前工作路径的名字(是一个绝对路径) echo 显示文本行 cat 连接文件内容,并打印到标准输出

MFC的窗口分割的设计与实现以及CSplitterWnd 类分析

1 引言 在Microsoft VC++ 6.0 中,基于MFC 的应用程序一般分为以下几种:多文档界面(MDI). 单文档界面(SDI)以及基于对话框的应用程序.其中单文档又可分为单视图的和多视图的, 一般情况下,单文档仅需要单视图就够了,如Windows 自带的记事本.画图程序等等,但 在一些情况下,单文档需要多视图支持,比如同时观察文档的不同部分,同时从不同的角度 观察同一文档等. 在MFC 的框架下,文档对象(CDocument)有一个保存其所有视图的列表,并提供了 增加视图(AddVi

Linux学习笔记--Linux文件管理类名利详解

Linux文件管理类命令详解 目录管理: ls.cd.pwd.mkdir.rmdir.tree 文件管理: touch.stat.file.rm.cp.mv.nano 日期管理: touch.clock.hwclock.cal 查看文本: cat.tac.more.less.head.tail cat:连接并显示 -n:在显示时显示每一行的行号 -E:在每行结束处显示 $ Ctrl+C:结束命令 分屏显示: more.less more:向后翻 less: q退出命令 head:查看前n行 ta

linux文件管理类命令,类型,用户的权限管理及bash shell的特性:命令别名,文件名通配

文件管理类命令 ls 查看 :cat tac more less head tail 复制:cp -r:递归 -i:提示,交互 -f:强制覆盖 -a :保留所有文件信息 -d:当源为链接文件时,复制链接本身,而非源文件 -p:保持原有属性 删除 : rm 删除非空目录 rm -rf 移动 : mv 创建 : touch 用来修改时间戳,创建空文件 -c:不创建新文件,只修改时间戳 -a:仅修改访问时间 -m:修改修改时间 -t:指定时间戳 先加-m再加-t后跟时间 元数据属性:stat 显示文件

cocos2dx[3.2](9) ——数学类Vec2/Size/Rect

[唠叨] 数学类Vec2.Size.Rect,是cocos2dx中比较常用的类. 比如设置图片位置,设置图片大小,两图片的碰撞检测等等. 比起2.x版本,在3.2中本质上其实没有太大的变化,主要的变化就是将全局宏定义相关的操作封装到各自的类中而已.比如:Vec2的向量运算宏定义ccp***(),现在都已经封装到Vec2类里面去了. [Vec2] Vec2原名Point,它既可以表示一个二维坐标点,又可以表示一个二维向量. 同时Vec2对运算符进行了重载,可以很方便的完成Vec2的赋值.加减乘除等

JAVA File类 分析(三)

前面两篇与大家一起研究了unix下的文件系统,本篇将和大家一起分析 文件的属性和文件夹. ok,废话不说,先来段代码 #include <stdio.h> #include <sys/types.h> #include <dirent.h> void do_ls(char[]); void main(int ac,char *av[]){ if(ac==1) do_ls("."); else{ while(--ac){ printf("%s