记录一下在cocos2dx中读取zip和解压zip
1.读取zip
获取可读写入路径,把zip文件拷到可读写路径下,如下
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;
}上面参数中password为zip压缩文件密码,在使用资源之前调用loadZIP即可2.解压zip
读取zip到内存,并且解压zip,如下
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的开头定义了
#ifndef NOUNCRYPT
#define NOUNCRYPT
#endif在unzOpenCurrentFile3中做了# ifndef NOUNCRYPT
char source[12];
# else
if (password != NULL)
return UNZ_PARAMERROR;
# endif
所以在开头注释掉#define NOUNCRYPT,这样就可以正常解压了
3.读取zip内容
因为解压出来的zip下内容的路径与正常读取资源时的路径不同,所以需要修改一下FileUtils::fullPathForFilename下的路径读取,只需要做如下修改
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方法,如下
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加密。
这篇博客介绍了在cocos2dx游戏中如何读取和解压zip文件,包括拷贝zip到可读写路径、解压到内存以及修改FileUtils的路径读取方式。同时,作者提到解压时需取消#define NOUNCRYPT注释,以确保正常解压。文章最后预告将探讨cocos2dx中的xxtea加密技术。
9776

被折叠的 条评论
为什么被折叠?



