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

cocos2dx-2.x CCFileUtils文件管理类分析,第1张

概述cocos2dx文件管理类是一个很重要的类,这里对这个类进行一下分析:CCFileUtils是文件管理类的基类,不同平台下android,ios,win32都有继承于这个类的子类,如androidclass CC_DLL CCFileUtilsAndroid : public CCFileUtils1、单例类:static CCFileUtils* sharedFileUtils()

cocos2dx文件管理类是一个很重要的类,这里对这个类进行一下分析:CCfileUtils是文件管理类的基类,不同平台下androID,ios,win32都有继承于这个类的子类,如androIDclass CC_DLL CCfileUtilsAndroID : public CCfileUtils1、单例类:static CCfileUtils* sharedfileUtils()而实现却在CCfileUtilsAndroID.cpp文件中:并且创建的是各个平台下的子类实例CCfileUtils* CCfileUtils::sharedfileUtils(){    if (s_sharedfileUtils == NulL)    {        s_sharedfileUtils = new CCfileUtilsAndroID();        s_sharedfileUtils->init();	//获取apk包的路径,这里是java端设置的。        std::string resourcePath = getApkPath();	// record the zip on the resource path        // static Zipfile *s_pZipfile = NulL;	// 因为androID的很多资源是放在安装包里的assets文件里,	//所以获取资源是需要从包里解压,这就用到了Zipfile类        s_pZipfile = new Zipfile(resourcePath,"assets/");    }    return s_sharedfileUtils;}2、初始化:bool CCfileUtilsAndroID::init(){    m_strDefaultResRootPath = "assets/"; //默认的资源路径,默认是安装包    return CCfileUtils::init(); -->> 1}1 -->> bool CCfileUtils::init(){    //m_searchPathArray -- 资源搜索路径数组    //m_searchResolutionsOrderArray -- 资源分辨率数组    m_searchPathArray.push_back(m_strDefaultResRootPath);    m_searchResolutionsOrderArray.push_back("");    return true;}




在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/",//m_searchResolutionsOrderArray     	and set three elements("resources-ipadhd/","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;}总结:这里需要知道一点,就是先加载搜索路径的路径,会优先搜索到。      比如热更新,我们只要把更新路径设置在前面即可。

在2中,我们分析了几个函数,在这一篇中我们继续分析其他一些函数。1、在2中,多次用到了m_searchPathArray(搜索路径),那这个搜索路径怎么来的呢?我们可以通过setSearchPaths这个函数来设置搜索路径voID CCfileUtils::setSearchPaths(const std::vector<std::string>& searchPaths){    bool bExistDefaultRootPath = false;    //先把以前的清空,包括缓存路径    m_fullPathCache.clear();    m_searchPathArray.clear();     //逐个加入到m_searchPathArray    for (std::vector<std::string>::const_iterator iter = searchPaths.begin(); iter != searchPaths.end(); ++iter)    {        std::string strPrefix;        std::string path;	//如果不是绝对路径,androID的则加上"assets/"前缀,表明需要去安装包里找        if (!isabsolutePath(*iter))        { // Not an absolute path            strPrefix = m_strDefaultResRootPath;        }	//如果路径不是以'/'结尾,则在结尾加上'/'        path = strPrefix+(*iter);        if (path.length() > 0 && path[path.length()-1] != '/')        {            path += "/";        }        if (!bExistDefaultRootPath && path == m_strDefaultResRootPath)        {            bExistDefaultRootPath = true;        }        m_searchPathArray.push_back(path);    }        if (!bExistDefaultRootPath)    {        //如果m_strDefaultResRootPath默认路径不在m_searchPathArray,则加入进来        //cclOG("Default root path doesn't exist,adding it.");        m_searchPathArray.push_back(m_strDefaultResRootPath);    }}-->>voID CCfileUtils::addSearchPath(const char* path_){    std::string strPrefix;    std::string path(path_);    if (!isabsolutePath(path))    { // Not an absolute path        strPrefix = m_strDefaultResRootPath;    }    path = strPrefix + path;    if (path.length() > 0 && path[path.length()-1] != '/')    {        path += "/";    }    m_searchPathArray.push_back(path);}//移除一个搜索路径:voID CCfileUtils::removeSearchPath(const char *path_){	std::string strPrefix;	std::string path(path_);	if (!isabsolutePath(path))	{ // Not an absolute path		strPrefix = m_strDefaultResRootPath;	}	path = strPrefix + path;	if (path.length() > 0 && path[path.length()-1] != '/')	{		path += "/";	}	std::vector<std::string>::iterator iter = std::find(m_searchPathArray.begin(),m_searchPathArray.end(),path);	m_searchPathArray.erase(iter);}//移除全部voID CCfileUtils::removeAllPaths(){	m_searchPathArray.clear();}2、m_searchResolutionsOrderArray资源路径和上面的一样处理方式,就不说了。3、从pszrelativefile这个文件的相对路径中,得到pszfilename文件的全路径,其实就是找到pszrelativefile文件的最后一个'/',然后去这个'/'前的所有字符 + pszfilename即可。const char* CCfileUtils::fullPathFromrelativefile(const char *pszfilename,const char *pszrelativefile){    std::string relativefile = pszrelativefile;    CCString *pRet = CCString::create("");    pRet->m_sstring = relativefile.substr(0,relativefile.rfind('/')+1);    pRet->m_sstring += getNewfilename(pszfilename);    return pRet->getCString();}4、//androID下的可读写路径string CCfileUtilsAndroID::getWritablePath(){    // Fix for Nexus 10 (AndroID 4.2 multi-user environment)    // the path is retrIEved through Java Context.getCacheDir() method    string dir("");    //pContext.getfilesDir().getabsolutePath() java端    string tmp = getfileDirectoryJNI(); //pContext.getfilesDir().getabsolutePath()    if (tmp.length() > 0)    {        dir.append(tmp).append("/");        return dir;    }    else    {        return "";    }}

在3中,我们又分析了几个函数,在这一篇中我们继续分析其他一些函数。1、androID平台unsigned char* CCfileUtilsAndroID::getfileData(const char* pszfilename,const char* pszMode,unsigned long * pSize){        return doGetfileData(pszfilename,pszMode,pSize,false);}-->>//pszfilename 文件名//pszMode 读取模式,只有对绝对路径有用,参数就是C API的类型//pSize 读出的字节大小//forAsync 同步还是异步unsigned char* CCfileUtilsAndroID::doGetfileData(const char* pszfilename,unsigned long * pSize,bool forAsync){    unsigned char * pData = 0;        if ((! pszfilename) || (! pszMode) || 0 == strlen(pszfilename))    {        return 0;    }        //先获取文件的全路径    string fullPath = fullPathForfilename(pszfilename);        if (fullPath[0] != '/')    {        //如果以"assets/"开头,即文件在安装包里,那么通过压缩文件类从压缩包中读取,	//其实androID的安装包就是压缩包。        if (forAsync)        {            pData = s_pZipfile->getfileData(fullPath.c_str(),s_pZipfile->_dataThread);        }        else        {            pData = s_pZipfile->getfileData(fullPath.c_str(),pSize);        }    }    else    {        do        {   	     //如果是绝对路径,则通过C API读取。            // read rrom other path than user set it	        //cclOG("GETTING file absolute DATA: %s",pszfilename);            file *fp = fopen(fullPath.c_str(),pszMode);            CC_BREAK_IF(!fp);                        unsigned long size;            fseek(fp,SEEK_END);            size = ftell(fp);            fseek(fp,SEEK_SET);            pData = new unsigned char[size];            size = fread(pData,sizeof(unsigned char),size,fp);            fclose(fp);                        if (pSize)            {                *pSize = size;            }        } while (0);    }        if (! pData)    {        std::string msg = "Get data from file(";        msg.append(pszfilename).append(") Failed!");        cclOG("%s",msg.c_str());    }        return pData;}总结:到此为止,cocos2dx-2.X androID平台的文件读出我已经通过源码的形式分析完了,做个记录,以防忘记。
总结

以上是内存溢出为你收集整理的cocos2dx-2.x CCFileUtils文件管理类分析全部内容,希望文章能够帮你解决cocos2dx-2.x CCFileUtils文件管理类分析所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1076618.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存