在cocos2dx中,提供了CCFileUitl来进行文件操作,但是大家一般习惯的方式还是仅仅通过这个类获取路径,然后用fopen相关的函数来操作,大概如下:
- string fullPath = fullPathForFilename(pszFileName);
- 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的实现如下:
- unsigned char* CCFileUtilsAndroid::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
- {
- return doGetFileData(pszFileName, pszMode, pSize, false);
- }
- unsigned char* CCFileUtilsAndroid::getFileDataForAsync(const char* pszFileName, const char* pszMode, unsigned long * pSize)
- {
- return doGetFileData(pszFileName, pszMode, pSize, true);
- }
- unsigned char* CCFileUtilsAndroid::doGetFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize, bool forAsync)
- {
- unsigned char * pData = 0;
- if ((! pszFileName) || (! pszMode) || 0 == strlen(pszFileName))
- {
- return 0;
- }
- string fullPath = fullPathForFilename(pszFileName);
- if (fullPath[0] != '/')
- {
- if (forAsync)
- { /********** !!!注意啊 ***********/
- pData = s_pZipFile->getFileData(fullPath.c_str(), pSize, s_pZipFile->_dataThread);
- }
- else
- {
- pData = s_pZipFile->getFileData(fullPath.c_str(), pSize);
- }
- }
- else
- {
- do
- {
- FILE *fp = fopen(fullPath.c_str(), pszMode);
- CC_BREAK_IF(!fp);
- unsigned long size;
- fseek(fp,0,SEEK_END);
- size = ftell(fp);
- fseek(fp,0,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;
- }
- #include "support/zip_support/ZipUtils.h"
- // record the zip on the resource path
- static ZipFile *s_pZipFile = NULL;
- CCFileUtils* CCFileUtils::sharedFileUtils()
- {
- if (s_sharedFileUtils == NULL)
- {
- s_sharedFileUtils = new CCFileUtilsAndroid();
- s_sharedFileUtils->init();
- std::string resourcePath = getApkPath();
- s_pZipFile = new ZipFile(resourcePath, "assets/");
- }
- return s_sharedFileUtils;
- }
- unsigned char *ZipFile::getFileData(const std::string &fileName, unsigned long *pSize, ZipFilePrivate *data)
- {
- unsigned char * pBuffer = NULL;
- if (pSize)
- {
- *pSize = 0;
- }
- do
- {
- CC_BREAK_IF(!data->zipFile);
- CC_BREAK_IF(fileName.empty());
- ZipFilePrivate::FileListContainer::const_iterator it = data->fileList.find(fileName);
- CC_BREAK_IF(it == data->fileList.end());
- ZipEntryInfo fileInfo = it->second;
- int nRet = unzGoToFilePos(data->zipFile, &fileInfo.pos);
- CC_BREAK_IF(UNZ_OK != nRet);
- nRet = unzOpenCurrentFile(data->zipFile);
- CC_BREAK_IF(UNZ_OK != nRet);
- pBuffer = new unsigned char[fileInfo.uncompressed_size];
- int CC_UNUSED nSize = unzReadCurrentFile(data->zipFile, pBuffer, fileInfo.uncompressed_size);
- CCAssert(nSize == 0 || nSize == (int)fileInfo.uncompressed_size, "the file size is wrong");
- if (pSize)
- {
- *pSize = fileInfo.uncompressed_size;
- }
- unzCloseCurrentFile(data->zipFile);
- } while (0);
- return pBuffer;
- }
一、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)