cocos2dx android fopen读取文件失败

来源:互联网 发布:抢单app源码 编辑:程序博客网 时间:2024/06/13 20:57

 在cocos2dx中,提供了CCFileUitl来进行文件操作,但是大家一般习惯的方式还是仅仅通过这个类获取路径,然后用fopen相关的函数来操作,大概如下:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. string fullPath = fullPathForFilename(pszFileName);  
  2. FILE *fp = fopen(fullPath.c_str(), pszMode);  

        但是这样,windows和iOS正常无误,但是在android下面,会读取不到文件。之前遇到这个问题,没有解决,后面为了统一,改成了CCFileUtil的getFileData就没有出现过,也没有继续去追。

        今天追了之后,发现,在android下,CCFileUtil有独立实现,在cocos2d-x-2.2.3/cocos2dx/platform/android/下面(引擎版本2.2.3),CCFileUtilsAndroid。其中getFileData的实现如下:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. unsigned char* CCFileUtilsAndroid::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)  
  2. {      
  3.     return doGetFileData(pszFileName, pszMode, pSize, false);  
  4. }  
  5. unsigned char* CCFileUtilsAndroid::getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize)  
  6. {  
  7.     return doGetFileData(pszFileName, pszMode, pSize, true);  
  8. }  
  9.   
  10. unsigned char* CCFileUtilsAndroid::doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync)  
  11. {  
  12.     unsigned char * pData = 0;  
  13.       
  14.     if ((! pszFileName) || (! pszMode) || 0 == strlen(pszFileName))  
  15.     {  
  16.         return 0;  
  17.     }  
  18.       
  19.     string fullPath = fullPathForFilename(pszFileName);  
  20.       
  21.     if (fullPath[0] != '/')  
  22.     {  
  23.         if (forAsync)  
  24.         {   /********** !!!注意啊  ***********/  
  25.             pData = s_pZipFile->getFileData(fullPath.c_str(), pSize, s_pZipFile->_dataThread);  
  26.         }  
  27.         else  
  28.         {  
  29.             pData = s_pZipFile->getFileData(fullPath.c_str(), pSize);  
  30.         }  
  31.     }  
  32.     else  
  33.     {  
  34.         do  
  35.         {  
  36.             FILE *fp = fopen(fullPath.c_str(), pszMode);  
  37.             CC_BREAK_IF(!fp);  
  38.               
  39.             unsigned long size;  
  40.             fseek(fp,0,SEEK_END);  
  41.             size = ftell(fp);  
  42.             fseek(fp,0,SEEK_SET);  
  43.             pData = new unsigned char[size];  
  44.             size = fread(pData,sizeof(unsigned char), size,fp);  
  45.             fclose(fp);  
  46.               
  47.             if (pSize)  
  48.             {  
  49.                 *pSize = size;  
  50.             }  
  51.         } while (0);  
  52.     }  
  53.       
  54.     if (! pData)  
  55.     {  
  56.         std::string msg = "Get data from file(";  
  57.         msg.append(pszFileName).append(") failed!");  
  58.         CCLOG("%s", msg.c_str());  
  59.     }  
  60.       
  61.     return pData;  
  62. }  
        注意上面代码里面我标记注释的地方,有个东西叫s_pZipFile,之前看到这里,没注意这个东西。仔细一看,前面的fullpath的返回值,是一个相对于asset/的文件,也就是说,基本上都会走这个if,那么这个s_pZipFile又是怎么定义的。        

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "support/zip_support/ZipUtils.h"  
  2.   
  3. // record the zip on the resource path  
  4. static ZipFile *s_pZipFile = NULL;  
  5.   
  6. CCFileUtils* CCFileUtils::sharedFileUtils()  
  7. {  
  8.     if (s_sharedFileUtils == NULL)  
  9.     {  
  10.         s_sharedFileUtils = new CCFileUtilsAndroid();  
  11.         s_sharedFileUtils->init();  
  12.         std::string resourcePath = getApkPath();  
  13.         s_pZipFile = new ZipFile(resourcePath, "assets/");  
  14.     }  
  15.     return s_sharedFileUtils;  
  16. }  
        重要的头文件我都留在上面了,所以其实上面那个getFileData的实现是这样的

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data)  
  2. {  
  3.     unsigned char * pBuffer = NULL;  
  4.     if (pSize)  
  5.     {  
  6.         *pSize = 0;  
  7.     }  
  8.       
  9.     do  
  10.     {  
  11.         CC_BREAK_IF(!data->zipFile);  
  12.         CC_BREAK_IF(fileName.empty());  
  13.           
  14.         ZipFilePrivate::FileListContainer::const_iterator it = data->fileList.find(fileName);  
  15.         CC_BREAK_IF(it ==  data->fileList.end());  
  16.           
  17.         ZipEntryInfo fileInfo = it->second;  
  18.           
  19.         int nRet = unzGoToFilePos(data->zipFile, &fileInfo.pos);  
  20.         CC_BREAK_IF(UNZ_OK != nRet);  
  21.           
  22.         nRet = unzOpenCurrentFile(data->zipFile);  
  23.         CC_BREAK_IF(UNZ_OK != nRet);  
  24.           
  25.         pBuffer = new unsigned char[fileInfo.uncompressed_size];  
  26.         int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);  
  27.         CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, "the file size is wrong");  
  28.           
  29.         if (pSize)  
  30.         {  
  31.             *pSize = fileInfo.uncompressed_size;  
  32.         }  
  33.         unzCloseCurrentFile(data->zipFile);  
  34.     } while (0);  
  35.       
  36.     return pBuffer;  
  37. }  
        基本上到这,问题就清楚了,总结起来就是2点

        一、assets其实是一个zip压缩文件,直接读取里面的内容是不行的。

        二、android的实现和其他2个平台不一样。


        解决办法:

        最简单的,直接用CCFileUtil的getFileData实现文件读取。

        不然就从上面提到的文件去改。。。




其他方法,参考:1、 http://www.cppblog.com/johndragon/archive/2012/12/28/196754.html 

     2、 http://blog.csdn.net/happyhell/article/details/7414110

(原文地址: http://blog.csdn.net/dinko321/article/details/41309735)

0 0