我正在搜索如何使用minizip从内存缓冲区打开存档。
我在他们的网页http://www.winimage.com/zLibDll/minizip.html找到了ioapi_mem_c.zip。
我无法理解如何使用它。有人可以举个例子吗?
答案 0 :(得分:6)
我解决了解压缩的问题: 我将此函数添加到unzip.c
extern unzFile ZEXPORT unzOpenBuffer (const void* buffer, uLong size)
{
char path[16] = {0};
zlib_filefunc64_32_def memory_file;
uLong base = (uLong)buffer;
sprintf(path, "%x+%x", base, size);
fill_memory_filefunc64_32(&memory_file);
return unzOpenInternal(path, &memory_file, 0);
}
并在ioapi_mem.c中进行了一些更改:
void fill_memory_filefunc64_32 (pzlib_filefunc_def)
zlib_filefunc64_32_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen32_file = fopen_mem_func;
pzlib_filefunc_def->zfile_func64.zopen64_file = fopen_mem_func;
pzlib_filefunc_def->zfile_func64.zread_file = fread_mem_func;
pzlib_filefunc_def->zfile_func64.zwrite_file = fwrite_mem_func;
pzlib_filefunc_def->ztell32_file = ftell_mem_func;
pzlib_filefunc_def->zseek32_file = fseek_mem_func;
pzlib_filefunc_def->zfile_func64.zseek64_file = NULL;
pzlib_filefunc_def->zfile_func64.zclose_file = fclose_mem_func;
pzlib_filefunc_def->zfile_func64.zerror_file = ferror_mem_func;
pzlib_filefunc_def->zfile_func64.opaque = NULL;
}
我希望这会帮助那些遇到同样问题的人。
以下是简单的类实现如何使用它:
void ZipArchiveImpl::OpenArchive()
{
ASSERT(!mInited, "Already opened.");
if ((mFileMode == FM_READ))
{
if (mArchiveName.size() == 0)
{
u32 sz = mFile->GetFileSize();
mUnzBlock.Resize(sz);
mFile->SetPosition(0);
mFile->Read(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes());
mUnzHandle = unzOpenBuffer(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes());
}
else
{
mUnzHandle = unzOpen(mArchiveName.c_str());
}
if (!mUnzHandle) return;
FillMap();
}
else if (mFileMode == FM_WRITE)
{
ASSERT0(mArchiveName.size());
mZipHandle = zipOpen(mArchiveName.c_str(), 0);
if (!mZipHandle) return;
}
mInited = true;
}
IFile* ZipArchiveImpl::OpenRead(const std::string& name)
{
if (IsExist(name))
{
ZipFileInfo info = mFileMap.find(name)->second;
MemoryBlock block(1);
block.Resize(info.uncompressedSize);
int res = unzGoToFilePos(mUnzHandle, &info.filePosInfo);
if (UNZ_OK != res)
{
return false;
}
// open the current file with optional password
if (mArchivePassword != "")
{
res = unzOpenCurrentFilePassword(info.zipFileHandle, mArchivePassword.c_str());
}
else
{
res = unzOpenCurrentFile(info.zipFileHandle);
}
if (UNZ_OK != res)
{
return false;
}
// read uncompressed data
int readResult = unzReadCurrentFile(info.zipFileHandle, block.Data(), info.uncompressedSize);
// close the file
res = unzCloseCurrentFile(info.zipFileHandle);
if (UNZ_OK != res)
{
return false;
}
if (info.uncompressedSize == readResult)
{
return ROBE_NEW MemoryFile(block.Data(), info.uncompressedSize);
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}
IFile* ZipArchiveImpl::OpenRead(u32 id)
{
ASSERT0(mFileNames.size() > id);
if (IsExist(mFileNames[id]))
{
return OpenRead(mFileNames[id]);
}
else
{
return NULL;
}
}
void ZipArchiveImpl::FillMap()
{
s32 walkRes = unzGoToFirstFile(mUnzHandle);
unz_file_info info;
while (UNZ_OK == walkRes)
{
// get info about current file
char currentFileName[512];
s32 fileInfoRes = unzGetCurrentFileInfo(mUnzHandle, &info, currentFileName, sizeof(currentFileName), 0, 0, 0, 0);
std::string name = std::string(currentFileName);
mFileNames.push_back(name);
InitInfo(name, &info);
walkRes = unzGoToNextFile(mUnzHandle);
}
OpenRead(0);
if (UNZ_END_OF_LIST_OF_FILE != walkRes)
{
}
}
void ZipArchiveImpl::InitInfo(const std::string& name, unz_file_info* info)
{
ZipFileInfo zfi;
mFileMap.insert(std::pair<std::string, ZipFileInfo>(name, zfi));
mFileMap[name].zipFileHandle = mUnzHandle;
int res = unzGetFilePos(mFileMap[name].zipFileHandle, &mFileMap[name].filePosInfo);
mFileMap[name].uncompressedSize = info->uncompressed_size;
char lastsymbol = name[name.size() - 1];
if (lastsymbol == '/' || lastsymbol == '\\')
{
mFileMap[name].type = ZFT_DIR;
}
else
{
mFileMap[name].type = ZFT_FILE;
}
}
ZipArchiveImpl::~ZipArchiveImpl()
{
if (mInited)
{
if (mUnzHandle) unzClose(mUnzHandle);
if (mZipHandle) zipClose(mZipHandle, 0);
}
}
bool ZipArchiveImpl::IsExist(const std::string& name)
{
return (mFileMap.find(name) != mFileMap.end());
}
void ZipArchiveImpl::SaveFileToZip(const std::string& path, IFile* file)
{
const u32 DefaultFileAttribute = 32;
MemoryBlock block(1);
block.Resize(file->GetFileSize());
file->Read(block.Data(), block.GetSizeInBytes());
zip_fileinfo zinfo;
memset(&zinfo, 0, sizeof(zinfo));
zinfo.internal_fa = 0;
zinfo.external_fa = DefaultFileAttribute;
::boost::posix_time::ptime pt = ::boost::posix_time::from_time_t(time(0));
std::tm ptm = ::boost::posix_time::to_tm(pt);
zinfo.dosDate = 0;
zinfo.tmz_date.tm_year = ptm.tm_year;
zinfo.tmz_date.tm_mon = ptm.tm_mon;
zinfo.tmz_date.tm_mday = ptm.tm_mday;
zinfo.tmz_date.tm_hour = ptm.tm_hour;
zinfo.tmz_date.tm_min = ptm.tm_min;
zinfo.tmz_date.tm_sec = ptm.tm_sec;
zipOpenNewFileInZip(mZipHandle, path.c_str(), &zinfo, 0, 0, 0, 0, 0, Z_DEFLATED, Z_BEST_SPEED);
zipWriteInFileInZip(mZipHandle, block.Data(), block.GetSizeInBytes());
zipCloseFileInZip(mZipHandle);
}
unsigned long ZipArchiveImpl::GetFileAttributes(const std::string& filePath)
{
unsigned long attrib = 0;
#ifdef WIN32
attrib = ::GetFileAttributes(filePath.c_str());
#else
struct stat path_stat;
if (::stat(filePath.c_str(), &path_stat) == 0)
{
attrib = path_stat.st_mode;
}
#endif
return attrib;
}
答案 1 :(得分:1)
将此函数添加到unzip.c
extern unzFile ZEXPORT unzOpenBuffer(const void* buffer, uLong size)
{
zlib_filefunc_def filefunc32 = { 0 };
ourmemory_t *punzmem = (ourmemory_t*)malloc(sizeof(ourmemory_t));
punzmem->size = size;
punzmem->base = (char *)malloc(punzmem->size);
memcpy(punzmem->base, buffer, punzmem->size);
punzmem->grow = 0;
punzmem->cur_offset = 0;
punzmem->limit = 0;
fill_memory_filefunc(&filefunc32, punzmem);
return unzOpen2(NULL, &filefunc32);
}
答案 2 :(得分:0)
查看链接中的代码,没有明显的方法来传递内存缓冲区。将内存缓冲区保存为文件,解压缩。
或者您可以实现自己的zlib_filefunc_def
变体,该变体在一块内存而不是文件上运行。我认为这很难做到。
答案 3 :(得分:-2)
签出minizip的nmoinvaz分支:要从内存中的zip文件解压缩,请使用fill_memory_filefunc并提供正确的ourmemory_t结构
zlib_filefunc_def filefunc32 = {0};
ourmemory_t unzmem = {0};
unzmem.size = bufsize;
unzmem.base = (char *)malloc(unzmem.size);
memcpy(unzmem.base, buffer, unzmem.size);
fill_memory_filefunc(&filefunc32, &unzmem);
unzOpen2("__notused__", &filefunc32);