cocos2dx中zip包读取解压使用

记录一下在cocos2dx中读取zip和解压zip

1.读取zip

获取可读写入路径,把zip文件拷到可读写路径下,如下

  1. boolResourcesDecode::loadZIP(conststd::string&zipFilename,conststd::string&password/*""*/)
  2. {
  3. std::stringfilename=zipFilename;
  4. std::stringdataFilePath=FileUtils::getInstance()->getWritablePath()+filename;
  5. #if(CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID||CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
  6. if(access(dataFilePath.c_str(),0)!=0)
  7. std::stringstrPath=FileUtils::getInstance()->fullPathForFilename(filename);
  8. ssize_tlen=0;
  9. unsignedchar*data=0;
  10. CCLOG("strPath:%s",strPath.c_str());
  11. data=FileUtils::getInstance()->getFileData(strPath.c_str(),"r",&len);
  12. CCLOG("file:%s,len:%zd",dataFilePath.c_str(),len);
  13. FILE*fp=fopen(dataFilePath.c_str(),"w+");
  14. if(!fp)
  15. {
  16. CCLOG("filenotfound!");
  17. }
  18. fwrite(data,sizeof(char),len,fp);
  19. fclose(fp);
  20. delete[]data;
  21. data=0;
  22. }
  23. #endif
  24. //解压
  25. unCompress(dataFilePath.c_str(),password);
  26. returntrue;
  27. }
上面参数中password为zip压缩文件密码,在使用资源之前调用loadZIP即可

2.解压zip

读取zip到内存,并且解压zip,如下

copy
    boolResourcesDecode::unCompress(constchar*pOutFileName,153); background-color:inherit; font-weight:bold">conststd::string&password)
  1. if(!pOutFileName){
  2. CCLOG("unCompress()-invalidarguments");
  3. return0;
  4. FileUtils*utils=FileUtils::getInstance();
  5. std::stringoutFileName=utils->fullPathForFilename(pOutFileName);
  6. //打开压缩文件
  7. unzFilezipfile=unzOpen(outFileName.c_str());
  8. if(!zipfile)
  9. CCLOG("cannotopendownloadedzipfile%s",outFileName.c_str());
  10. false;
  11. //获取zip文件信息
  12. unz_global_infoglobal_info;
  13. if(unzGetGlobalInfo(zipfile,&global_info)!=UNZ_OK)
  14. CCLOG("cannotreadfileglobalinfoof%s",outFileName.c_str());
  15. unzClose(zipfile);
  16. //临时缓存,用于从zip中读取数据,然后将数据给解压后的文件
  17. charreadBuffer[BUFFER_SIZE];
  18. //开始解压缩
  19. CCLOG("startuncompressing");
  20. //根据自己压缩方式修改文件夹的创建方式
  21. std::stringstorageDir;
  22. intpos=outFileName.find_last_of("/");
  23. storageDir=outFileName.substr(0,pos);
  24. //FileUtils::getInstance()->createDirectory(storageDir);
  25. //循环提取压缩包内文件
  26. //global_info.number_entry为压缩包内文件个数
  27. uLongi;
  28. for(i=0;i<global_info.number_entry;++i)
  29. //获取压缩包内的文件
  30. unz_file_infofileInfo;
  31. charfileName[MAX_FILENAME];
  32. if(unzGetCurrentFileInfo(zipfile,
  33. &fileInfo,
  34. fileName,
  35. MAX_FILENAME,248); line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> NULL,108); list-style-type:decimal-leading-zero; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> 0,108); list-style-type:decimal-leading-zero; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> 0)!=UNZ_OK)
  36. CCLOG("cannotreadfileinfo");
  37. unzClose(zipfile);
  38. false;
  39. //该文件存放路径
  40. std::stringfullPath=storageDir+"/"+fileName;
  41. //检测路径是文件夹还是文件
  42. size_tfilenameLength=strlen(fileName);
  43. if(fileName[filenameLength-1]=='/')
  44. //该文件是一个文件夹,那么就创建它
  45. if(!FileUtils::getInstance()->createDirectory(fullPath.c_str()))
  46. CCLOG("cannotcreatedirectory%s",fullPath.c_str());
  47. else
  48. //该文件是一个文件,那么就提取创建它
  49. if(password.empty())
  50. if(unzOpenCurrentFile(zipfile)!=UNZ_OK)
  51. CCLOG("cannotopenfile%s",fileName);
  52. }else
  53. if(unzOpenCurrentFilePassword(zipfile,password.c_str())!=UNZ_OK)
  54. //创建目标文件
  55. FILE*out=fopen(fullPath.c_str(),"wb");
  56. if(!out)
  57. CCLOG("cannotopendestinationfile%s",108); list-style-type:decimal-leading-zero; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important; list-style-position:outside!important"> unzCloseCurrentFile(zipfile);
  58. //将压缩文件内容写入目标文件
  59. interror=UNZ_OK;
  60. do
  61. error=unzReadCurrentFile(zipfile,readBuffer,BUFFER_SIZE);
  62. if(error<0)
  63. CCLOG("cannotreadzipfile%s,errorcodeis%d",fileName,error);
  64. unzCloseCurrentFile(zipfile);
  65. if(error>0)
  66. fwrite(readBuffer,error,1,out);
  67. while(error>0);
  68. fclose(out);
  69. //关闭当前被解压缩的文件
  70. //如果zip内还有其他文件,则将当前文件指定为下一个待解压的文件
  71. if((i+1)<global_info.number_entry)
  72. if(unzGoToNextFile(zipfile)!=UNZ_OK)
  73. CCLOG("cannotreadnextfile");
  74. //压缩完毕
  75. CCLOG("enduncompressing");
  76. //压缩完毕删除zip文件删除前要先关闭
  77. if(remove(outFileName.c_str())!=0)
  78. CCLOG("cannotremovedownloadedzipfile%s",153); background-color:inherit; font-weight:bold">true;
  79. }

在有password密码时使用的是unzip的unzOpenCurrentFilePassword调用 unzOpenCurrentFile3,听说zlib库被某某某机构下令不准加密,有可能这样所以cocos2dx就在unzip.cpp的开头定义了
copy
    #ifndefNOUNCRYPT
  1. #defineNOUNCRYPT
  2. #endif
unzOpenCurrentFile3中做了
copy
    charsource[12];
  1. #else
  2. if(password!=NULL)
  3. returnUNZ_PARAMERROR;
  4. #endif

所以在开头注释掉#define NOUNCRYPT,这样就可以正常解压了

3.读取zip内容

因为解压出来的zip下内容的路径与正常读取资源时的路径不同,所以需要修改一下FileUtils::fullPathForFilename下的路径读取,只需要做如下修改

copy
    if(isPopupNotify()){
  1. if(fullpath.empty())
  2. fullpath=ResourcesDecode::getInstance()->findPathWithZip(filename);
  3. if(fullpath.size()==0)
  4. return"";
  5. returnfullpath;
  6. CCLOG("cocos2d:fullPathForFilename:Nofilefoundat%s.Possiblemissingfile.",filename.c_str());
  7. 当fullPathForFilename本身处理后的fullpath为空的时候,就去执行findPathWithzip方法,如下

    copy

      std::stringdataFilePath=FileUtils::getInstance()->getWritablePath()+filename;
    1. CCLOG("notfindinDocuments:%s",filename.c_str());
    2. returndataFilePath;
    经过上面处理即可获取到正常的资源。

    本文参考总结了一些文章,互相借鉴,有啥不对和优化的地方,欢迎评论,下篇写一下cocos2dx中用到的xxtea加密。

    相关文章

    操作步骤 1、创建cocos2d-x工程 2、新建 Scene1.cpp Scene1.h Scene1.h代码 #ifndef __SCENE1_H__#defi...
    开发环境:OS(WINDOWS 8.1 X64 企业版) cocos2d-x 2.2.1 vs2010 想给vs安装上cocos的模版,执行Install...
    把创建项目做成一个批处理,当创建项目时可以省时省力很多。 操作步骤 1、在 E:cocos2d-x-2.2.1toolspr...
    https://www.cnblogs.com/JiaoQing/p/3906780.html 四个响应函数 1 EventListenerPhysicsContact* evC...
    转载于 http://www.cnblogs.com/kenkofox/p/3926797.html 熟悉js的dom事件或者flash事件的,基本都能立...
    ScrollView(滚动容器)加载大量item时会导致游戏界面的卡顿,严重时整个界面会出现卡死的情况。最近项...