cocos2d-x-使用fopen函数读取assets里的内容导致crash

cocos2d-x-使用fopen函数读取assets里的内容导致crash

作者:Alex Zhou 时间:2012-11-25 标签:android开发专栏cocos2d-x开发专栏crashfopen读取assets
文章摘要: 最近把win32和ios上运行成功的游戏移植到android时,程序直接挂了,查到原因是:使用fopen读取assets里的数据会导致应用crash,因为数据已经被压缩打包进apk文件里了。 解决办法: 1.使用cocos2d-x提供的CCFileUtils工具类 2.把assets中的文件读取出来复制到/data/data/you_app_packagename/或者sd卡目录下,然后再使用…

最近把win32和ios上运行成功的游戏移植到android时,程序直接挂了,查到原因是:使用fopen读取assets里的数据会导致应用crash,因为数据已经被压缩打包进apk文件里了。
解决办法:
1.使用cocos2d-x提供的CCFileUtils工具类
2.把assets中的文件读取出来复制到/data/data/you_app_packagename/或者sd卡目录下,然后再使用fopen函数读取。
下面来看看如何使用CCFileUtils工具类读取assets目录下的文件,代码如下:

1
2
3
4
5
6
7
8
//获得文件在系统的绝对路径
const char *filepath = CCFileUtils::fullPathFromRelativePath(filename);
//读取的字节数,读取失败则为0
unsigned long len = 0;
//读取的内容
unsigned char *data = CCFileUtils::getFileData(filepath, "r" , &len);;
//记得释放内存
if (len >0 && data) delete [] data;

cocos2d-x会根据具体的平台调用CCFileUtils对应的实现类,win32是CCFileUtils_win32.cpp,android平台是CCFileUtils_andorid.cpp,
下面是CCFileUtils_andorid.cpp文件的部分源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
unsigned char * CCFileUtils::getFileData( const char * pszFileName, const char * pszMode, unsigned long * pSize)
{  
     unsigned char * pData = 0;
     string fullPath(pszFileName);
 
     if ((! pszFileName) || (! pszMode))
     {
         return 0;
     }
 
     if (pszFileName[0] != '/' )
     {
         // read from apk
         fullPath.insert(0, "assets/" );
         pData =  CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), fullPath.c_str(), pSize);
     }
     else
     {
         do
         {
             // read rrom other path than user set it
             FILE *fp = fopen (pszFileName, 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 && getIsPopupNotify())
     {
         std::string title = "Notification" ;
         std::string msg = "Get data from file(" ;
         msg.append(fullPath.c_str()).append( ") failed!" );
         CCMessageBox(msg.c_str(), title.c_str());
     }
 
     return pData;
}

当读取的文件名称是类似于”/test.txt”时,是使用fopen()函数的,这不是读取apk文件里的文件,是没有问题的,比如读取/data/data/packagename/xxx.txt。
最近我在android平台使用fopen()函数时,出现了很多问题,如下面代码:

1
2
3
4
5
6
7
FILE * m_pFile = fopen (filepath, "r" );
char ch = getc (m_pFile);
while (ch != EOF)
{
...
ch= getc (m_pFile);
}

在android平台这个while循环会无限循环,导致模拟器黑屏了。原来读到文件末尾时,ch的值为255,不等于EOF,改成while(ch != EOF && ch!= 255)就行了。
当文件名称是”test.txt”时,此时调用的是getFileDataFromZip()这个函数,读取apk压缩包assets里的文件。

下面附上把apk中assets目录下的文件拷贝到/data/data/${packagename}/下的代码(不过复制之前你应该先判断一下文件是否存在):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
bool isFileExist( const char * pFileName)
{
     if ( !pFileName ) return false ;
     //strFilePathName is :/data/data/ + package name
     std::string filePath = CCFileUtils::getWriteablePath();
     filePathName += pFileName;
 
     FILE *fp = fopen (filePath.c_str(), "r" );
     if (fp)
     {
         fclose (fp);
         return true ;
     }
     return false ;
}
 
void copyData( const char * pFileName)
{
     std::string strPath = CCFileUtils::fullPathFromRelativePath(pFileName);
     unsigned long len = 0;
     unsigned char *data = NULL;
 
     data = CCFileUtils::getFileData(strPath.c_str(), "r" ,&len);
     std::string destPath = CCFileUtils::getWriteablePath();
     destPath += pFileName;
     FILE *fp = fopen (destPath.c_str(), "w+" );
     fwrite (data, sizeof ( char ),len,fp);
     fclose (fp);
     delete []data;
     data = NULL;
}

转载请注明来自:Alex Zhou的程序世界,本文链接:http://codingnow.cn/cocos2d-x/939.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值