cocos集成了解压的功能,但为方便我单独提取出来。
ZipArchive类是放在libcocos2d/extension/assetsmanager目录下的
ZipArchive.h
#ifndef _ZIPARCHIVE_H_
#define _ZIPARCHIVE_H_
#include "cocos2d.h"
#include "cocos-ext.h"
NS_CC_EXT_BEGIN
class CC_EX_DLL ZipArchive
{
public:
ZipArchive();
~ZipArchive();
bool decompress(const std::string &zip);
private:
std::string basename(const std::string& path) const;
FileUtils *_fileUtils;
};
NS_CC_EXT_END
#endif
ZipArchive.cpp
#include "ZipArchive.h"
#include "stdio.h"
#include "sys/stat.h"
#ifdef MINIZIP_FROM_SYSTEM
#include <minizip/unzip.h>
#else // from our embedded sources
#include "unzip.h"
#endif
NS_CC_EXT_BEGIN
#define BUFFER_SIZE 8192
#define MAX_FILENAME 512
ZipArchive::ZipArchive()
{
_fileUtils = FileUtils::getInstance();
}
ZipArchive::~ZipArchive()
{
}
bool ZipArchive::decompress(const std::string &zip)
{
// Find root path for zip file
size_t pos = zip.find_last_of("/\\");
if (pos == std::string::npos)
{
log("AssetsManagerEx : no root path specified for zip file %s\n", zip.c_str());
return false;
}
const std::string rootPath = zip.substr(0, pos + 1);
// Open the zip file
unzFile zipfile = unzOpen(FileUtils::getInstance()->getSuitableFOpen(zip).c_str());
if (!zipfile)
{
log("AssetsManagerEx : can not open downloaded zip file %s\n", zip.c_str());
return false;
}
// Get info about the zip file
unz_global_info global_info;
if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK)
{
log("AssetsManagerEx : can not read file global info of %s\n", zip.c_str());
unzClose(zipfile);
return false;
}
// Buffer to hold data read from the zip file
char readBuffer[BUFFER_SIZE];
// Loop to extract all files.
uLong i;
for (i = 0; i < global_info.number_entry; ++i)
{
// Get info about current file.
unz_file_info fileInfo;
char fileName[MAX_FILENAME];
if (unzGetCurrentFileInfo(zipfile,
&fileInfo,
fileName,
MAX_FILENAME,
NULL,
0,
NULL,
0) != UNZ_OK)
{
log("AssetsManagerEx : can not read compressed file info\n");
unzClose(zipfile);
return false;
}
const std::string fullPath = rootPath + fileName;
// Check if this entry is a directory or a file.
const size_t filenameLength = strlen(fileName);
if (fileName[filenameLength - 1] == '/')
{
//There are not directory entry in some case.
//So we need to create directory when decompressing file entry
if (!_fileUtils->createDirectory(basename(fullPath)))
{
// Failed to create directory
log("AssetsManagerEx : can not create directory %s\n", fullPath.c_str());
unzClose(zipfile);
return false;
}
}
else
{
// Create all directories in advance to avoid issue
std::string dir = basename(fullPath);
if (!_fileUtils->isDirectoryExist(dir)) {
if (!_fileUtils->createDirectory(dir)) {
// Failed to create directory
log("AssetsManagerEx : can not create directory %s\n", fullPath.c_str());
unzClose(zipfile);
return false;
}
}
// Entry is a file, so extract it.
// Open current file.
if (unzOpenCurrentFile(zipfile) != UNZ_OK)
{
log("AssetsManagerEx : can not extract file %s\n", fileName);
unzClose(zipfile);
return false;
}
// Create a file to store current file.
FILE *out = fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), "wb");
if (!out)
{
log("AssetsManagerEx : can not create decompress destination file %s (errno: %d)\n", fullPath.c_str(), errno);
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
return false;
}
// Write current file content to destinate file.
int error = UNZ_OK;
do
{
error = unzReadCurrentFile(zipfile, readBuffer, BUFFER_SIZE);
if (error < 0)
{
log("AssetsManagerEx : can not read zip file %s, error code is %d\n", fileName, error);
fclose(out);
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
return false;
}
if (error > 0)
{
fwrite(readBuffer, error, 1, out);
}
} while (error > 0);
fclose(out);
}
unzCloseCurrentFile(zipfile);
// Goto next entry listed in the zip file.
if ((i + 1) < global_info.number_entry)
{
if (unzGoToNextFile(zipfile) != UNZ_OK)
{
log("AssetsManagerEx : can not read next file for decompressing\n");
unzClose(zipfile);
return false;
}
}
}
unzClose(zipfile);
_fileUtils->removeFile(zip);
return true;
}
std::string ZipArchive::basename(const std::string& path) const
{
size_t found = path.find_last_of("/\\");
if (std::string::npos != found)
{
return path.substr(0, found);
}
else
{
return path;
}
}
NS_CC_EXT_END
调用方法:
#include "extension/assets-manager/ZipArchive.h"
void zzip()
{
//获取文件路径
std::string str = FileUtils::getInstance()->getWritablePath() + "Resources.zip";
const char* file_path = str.c_str();
log("external file path = %s", file_path);
cocos2d::extension::ZipArchive * zip = new cocos2d::extension::ZipArchive();
zip->decompress(str);
}