记录一下在cocos2dx中读取zip和解压zip 1.读取zip 获取可读写入路径,把zip文件拷到可读写路径下,如下 [cpp] view plain copy bool ResourcesDecode::loadZIP( const std::stringzipFilename, const std::stringpasswor
记录一下在cocos2dx中读取zip和解压zip
1.读取zip
获取可读写入路径,把zip文件拷到可读写路径下,如下
[cpp] view plain copy
- bool ResourcesDecode::loadZIP(const std::string &zipFilename,const std::string &password/*""*/)
- {
- std::string filename = zipFilename;
- std::string dataFilePath = FileUtils::getInstance()->getWritablePath() + filename;
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
- if(access(dataFilePath.c_str(), 0) != 0)
- {
- std::string strPath = FileUtils::getInstance()->fullPathForFilename(filename);
- ssize_t len = 0;
- unsigned char *data = 0;
- CCLOG("strPath:%s",strPath.c_str());
- data = FileUtils::getInstance()->getFileData(strPath.c_str(), "r", &len);
- CCLOG("file:%s, len:%zd", dataFilePath.c_str(), len);
- FILE* fp = fopen(dataFilePath.c_str(), "w+");
- if(!fp)
- {
- CCLOG("file not found!");
- }
- fwrite(data, sizeof(char), len, fp);
- fclose(fp);
- delete []data;
- data = 0;
- }
- #endif
- //解压
- unCompress(dataFilePath.c_str(),password);
- return true;
- }
2.解压zip
读取zip到内存,并且解压zip,如下
[cpp] view plain copy
- bool ResourcesDecode::unCompress(const char * pOutFileName,const std::string &password)
- {
- if (!pOutFileName) {
- CCLOG("unCompress() - invalid arguments");
- return 0;
- }
- FileUtils *utils = FileUtils::getInstance();
- std::string outFileName = utils->fullPathForFilename(pOutFileName);
- // 打开压缩文件
- unzFile zipfile = unzOpen(outFileName.c_str());
- if (! zipfile)
- {
- CCLOG("can not open downloaded zip file %s", outFileName.c_str());
- return false;
- }
- // 获取zip文件信息
- unz_global_info global_info;
- if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK)
- {
- CCLOG("can not read file global info of %s", outFileName.c_str());
- unzClose(zipfile);
- return false;
- }
- // 临时缓存,用于从zip中读取数据,然后将数据给解压后的文件
- char readBuffer[BUFFER_SIZE];
- //开始解压缩
- CCLOG("start uncompressing");
- //根据自己压缩方式修改文件夹的创建方式
- std::string storageDir;
- int pos = outFileName.find_last_of("/");
- storageDir = outFileName.substr(0,pos);
- // FileUtils::getInstance()->createDirectory(storageDir);
- // 循环提取压缩包内文件
- // global_info.number_entry为压缩包内文件个数
- uLong i;
- for (i = 0; i < global_info.number_entry; ++i)
- {
- // 获取压缩包内的文件名
- unz_file_info fileInfo;
- char fileName[MAX_FILENAME];
- if (unzGetCurrentFileInfo(zipfile,
- &fileInfo,
- fileName,
- MAX_FILENAME,
- NULL,
- 0,
- NULL,
- 0) != UNZ_OK)
- {
- CCLOG("can not read file info");
- unzClose(zipfile);
- return false;
- }
- //该文件存放路径
- std::string fullPath = storageDir + "/"+fileName;
- // 检测路径是文件夹还是文件
- const size_t filenameLength = strlen(fileName);
- if (fileName[filenameLength-1] == '/')
- {
- // 该文件是一个文件夹,那么就创建它
- if (!FileUtils::getInstance()->createDirectory(fullPath.c_str()))
- {
- CCLOG("can not create directory %s", fullPath.c_str());
- unzClose(zipfile);
- return false;
- }
- }
- else
- {
- // 该文件是一个文件,那么就提取创建它
- if(password.empty())
- {
- if (unzOpenCurrentFile(zipfile) != UNZ_OK)
- {
- CCLOG("can not open file %s", fileName);
- unzClose(zipfile);
- return false;
- }
- }else
- {
- if (unzOpenCurrentFilePassword(zipfile,password.c_str())!=UNZ_OK)
- {
- CCLOG("can not open file %s", fileName);
- unzClose(zipfile);
- return false;
- }
- }
- // 创建目标文件
- FILE *out = fopen(fullPath.c_str(), "wb");
- if (! out)
- {
- CCLOG("can not open destination file %s", fullPath.c_str());
- unzCloseCurrentFile(zipfile);
- unzClose(zipfile);
- return false;
- }
- // 将压缩文件内容写入目标文件
- int error = UNZ_OK;
- do
- {
- error = unzReadCurrentFile(zipfile, readBuffer, BUFFER_SIZE);
- if (error < 0)
- {
- CCLOG("can not read zip file %s, error code is %d", fileName, error);
- unzCloseCurrentFile(zipfile);
- unzClose(zipfile);
- return false;
- }
- if (error > 0)
- {
- fwrite(readBuffer, error, 1, out);
- }
- } while(error > 0);
- fclose(out);
- }
- //关闭当前被解压缩的文件
- unzCloseCurrentFile(zipfile);
- // 如果zip内还有其他文件,则将当前文件指定为下一个待解压的文件
- if ((i+1) < global_info.number_entry)
- {
- if (unzGoToNextFile(zipfile) != UNZ_OK)
- {
- CCLOG("can not read next file");
- unzClose(zipfile);
- return false;
- }
- }
- }
- //压缩完毕
- CCLOG("end uncompressing");
- //压缩完毕删除zip文件,删除前要先关闭
- unzClose(zipfile);
- if (remove(outFileName.c_str()) != 0)
- {
- CCLOG("can not remove downloaded zip file %s", outFileName.c_str());
- }
- return true;
- }
在有password密码时使用的是unzip的unzOpenCurrentFilePassword调用的 unzOpenCurrentFile3,听说zlib库被某某某机构下令不准加密,有可能这样所以cocos2dx就在unzip.cpp的开头定义了 [cpp] view plain copy
- #ifndef NOUNCRYPT
- #define NOUNCRYPT
- #endif
- # ifndef NOUNCRYPT
- char source[12];
- # else
- if (password != NULL)
- return UNZ_PARAMERROR;
- # endif
所以在开头注释掉#define NOUNCRYPT,这样就可以正常解压了
3.读取zip内容
因为解压出来的zip下内容的路径与正常读取资源时的路径不同,所以需要修改一下FileUtils::fullPathForFilename下的路径读取,只需要做如下修改
[cpp] view plain copy
- if(isPopupNotify()){
- if (fullpath.empty())
- {
- fullpath = ResourcesDecode::getInstance()->findPathWithZip(filename);
- if (fullpath.size() == 0)
- {
- return "";
- }
- return fullpath;
- }
- CCLOG("cocos2d: fullPathForFilename: No file found at %s. Possible missing file.", filename.c_str());
- }
当fullPathForFilename本身处理后的fullpath为空的时候,就去执行findPathWithzip方法,如下
[cpp] view plain copy
- std::string dataFilePath = FileUtils::getInstance()->getWritablePath() + filename;
- if(access(dataFilePath.c_str(), 0) != 0)
- {
- CCLOG("not find in Documents:%s",filename.c_str());
- return "";
- }
- return dataFilePath;
本文参考总结了一些文章,互相借鉴,有啥不对和优化的地方,欢迎评论,下篇写一下cocos2dx中用到的xxtea加密。