当一段buffer为zip压缩内容时,如何解压缩呢,这里直接贴上代码
bool UnZipMemFile(MemFile* memfile, const std::wstring& dest_folder, zip_progress_callback cb_func, void* pVoid)
{
zlib_filefunc_def zip_funcs;
std::string strPathAnsi;
int nRetCode;
__int64 total_size = 0;
DWORD dwResBuffer = 0;
zip_funcs.zopen_file = ZipOpenFunc;
zip_funcs.zread_file = ZipReadFunc;
zip_funcs.zwrite_file = ZipWriteFunc;
zip_funcs.ztell_file = ZipTellFunc;
zip_funcs.zseek_file = ZipSeekFunc;
zip_funcs.zclose_file = ZipCloseFunc;
zip_funcs.zerror_file = ZipErrorFunc;
zip_funcs.opaque=NULL;
void* hZip = unzOpen2((const char*)memfile, &zip_funcs);
if (NULL == hZip)
return false;
bool retval = false;
std::wstring dest_root = dest_folder;
FormatWinPath(dest_root);
wchar_t ch = dest_folder[dest_folder.size() - 1];
if (ch != L'\\')
dest_root += L'\\';
__int64 curpos = 0;
std::string read_buffer;
std::wstring last_path = dest_root;
CreateDirectoryRecur(last_path);
nRetCode = unzGoToFirstFile(hZip);
while (UNZ_OK == nRetCode)
{
char szCurrentFile[260];
unz_file_info fileInfo;
uLong dwSeekPos;
uLong dwSize;
nRetCode = unzGetCurrentFileInfo(
hZip,
&fileInfo,
szCurrentFile,
sizeof(szCurrentFile),
NULL,
0,
NULL,
0
);
if (nRetCode != UNZ_OK)
goto clean0;
dwSeekPos = unzGetOffset(hZip);
dwSize = fileInfo.uncompressed_size;
if (dwSize > 0)
{
std::wstring tmp_path;
std::wstring filename = dest_root + AnsiToUnicode(szCurrentFile, -1);
FormatWinPath(filename);
for (int i = filename.size() - 1; i > 0; i--)
{
if (filename[i] == L'\\')
{
tmp_path = filename.substr(0, i);
break;
}
}
if (tmp_path != last_path)
{
last_path = tmp_path;
CreateDirectoryRecur(tmp_path);
}
nRetCode = unzOpenCurrentFile(hZip);
if (nRetCode == UNZ_OK)
{
read_buffer.resize(dwSize + 4);
nRetCode = unzReadCurrentFile(hZip, (void*)read_buffer.data(), dwSize);
FILE* fp = _wfopen(filename.c_str(), L"wb");
if (fp)
{
fwrite(read_buffer.data(), 1, dwSize, fp);
fclose(fp);
}
unzCloseCurrentFile(hZip);
curpos += dwSize;
if (cb_func)
cb_func(curpos, memfile->GetFileSize(), pVoid);
}
}
nRetCode = unzGoToNextFile(hZip);
}
if (cb_func)
cb_func(memfile->GetFileSize(), memfile->GetFileSize(), pVoid);
clean0:
return retval;
}
其中的几个回调函数为:
void* ZipOpenFunc(void* opaque, const char* filename, int mode)
{
return (void*)filename;
}
uLong ZipReadFunc(void* opaque, void* stream, void* buf, uLong size)
{
uLong ret = 0;
MemFile* pMemFile = (MemFile*)stream;
if (!pMemFile)
goto clean0;
pMemFile->ReadFile(buf, size, &ret);
clean0:
return ret;
}
uLong ZipWriteFunc(void* opaque, void* stream, const void* buf, uLong size)
{
uLong ret = 0;
MemFile* pMemFile = (MemFile*)stream;
if (!pMemFile)
goto clean0;
pMemFile->WriteFile(buf, size, &ret);
clean0:
return ret;
}
long ZipSeekFunc (void* opaque, void* stream, uLong offset, int origin)
{
uLong ret = -1;
MemFile* pMemFile = (MemFile*)stream;
DWORD dwRetCode;
if (!pMemFile)
goto clean0;
dwRetCode = pMemFile->SetFilePointer(offset, NULL, origin);
if (INVALID_SET_FILE_POINTER == dwRetCode)
goto clean0;
ret = 0;
clean0:
return ret;
}
long ZipTellFunc(void* opaque, void* stream)
{
long ret=-1;
MemFile* pMemFile = (MemFile*)stream;
DWORD dwRetCode;
if (!pMemFile)
goto clean0;
dwRetCode = pMemFile->SetFilePointer(0, NULL, FILE_CURRENT);
if (INVALID_SET_FILE_POINTER == dwRetCode)
goto clean0;
ret = dwRetCode;
clean0:
return ret;
}
int ZipCloseFunc(void* opaque, void* stream)
{
int ret=-1;
MemFile* pMemFile = (MemFile*)stream;
if (!pMemFile)
goto clean0;
if (!pMemFile->CloseHandle())
goto clean0;
ret = 0;
clean0:
return ret;
}
int ZipErrorFunc(void* opaque, void* stream)
{
return 0;
}
void FormatFilePath(std::wstring & filepath)
{
int len = filepath.length();
for(int i=0; i<len; i++)
{
if (filepath[i] == L'/')
filepath[i] = L'\\';
}
}
其中用到了一个MemFile类,这个类的源代码网上很多,也很简单,也贴出代码吧:
class AURORA_EXPORT MemFile
{
public:
MemFile();
MemFile(PVOID lpBuffer, DWORD dwLength);
virtual ~MemFile();
void SetData(PVOID lpBuffer, DWORD dwLength);
BOOL ReadFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead);
BOOL WriteFile(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten);
DWORD SetFilePointer(
ULONG lDistanceToMove,
PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod
);
BOOL CloseHandle();
__int64 GetFileSize();
private:
CAtlArray<BYTE> m_buffer;
DWORD m_dwCurrentPos;
};
MemFile::MemFile()
{
}
MemFile::MemFile(PVOID lpBuffer, DWORD dwLength)
: m_dwCurrentPos(0)
{
m_buffer.SetCount(dwLength);
memcpy(m_buffer.GetData(), lpBuffer, dwLength);
}
MemFile::~MemFile()
{
}
void MemFile::SetData(PVOID lpBuffer, DWORD dwLength)
{
m_buffer.SetCount(dwLength);
memcpy(m_buffer.GetData(), lpBuffer, dwLength);
}
__int64 MemFile::GetFileSize()
{
return m_buffer.GetCount();
}
BOOL MemFile::ReadFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead)
{
BOOL retval = FALSE;
DWORD dwReaded;
if (!lpBuffer || !nNumberOfBytesToRead)
goto clean0;
if (m_dwCurrentPos + nNumberOfBytesToRead <= m_buffer.GetCount())
{
dwReaded = nNumberOfBytesToRead;
}
else
{
dwReaded = (DWORD)m_buffer.GetCount() - m_dwCurrentPos;
}
if (0 == dwReaded)
goto clean0;
memcpy(lpBuffer, m_buffer.GetData() + m_dwCurrentPos, dwReaded);
m_dwCurrentPos += dwReaded;
if (lpNumberOfBytesRead)
*lpNumberOfBytesRead = dwReaded;
retval = TRUE;
clean0:
return retval;
}
BOOL MemFile::WriteFile(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten)
{
BOOL retval = FALSE;
DWORD dwWritten = nNumberOfBytesToWrite;
if (!lpBuffer || !nNumberOfBytesToWrite)
goto clean0;
if (m_dwCurrentPos + nNumberOfBytesToWrite > m_buffer.GetCount())
{
m_buffer.SetCount(m_dwCurrentPos + nNumberOfBytesToWrite);
}
memcpy(m_buffer.GetData() + m_dwCurrentPos, lpBuffer, dwWritten);
m_dwCurrentPos += dwWritten;
if (lpNumberOfBytesWritten)
*lpNumberOfBytesWritten = dwWritten;
retval = TRUE;
clean0:
return retval;
}
DWORD MemFile::SetFilePointer(
ULONG lDistanceToMove,
PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod
)
{
DWORD retval = INVALID_SET_FILE_POINTER;
if (FILE_CURRENT == dwMoveMethod)
{
if (lDistanceToMove > 0)
{
if (m_dwCurrentPos + lDistanceToMove < m_buffer.GetCount())
{
m_dwCurrentPos += lDistanceToMove;
}
else
{
goto clean0;
}
}
else
{
if (m_dwCurrentPos >= lDistanceToMove)
{
m_dwCurrentPos += lDistanceToMove;
}
else
{
goto clean0;
}
}
}
else if (FILE_END == dwMoveMethod)
{
if (lDistanceToMove > 0)
goto clean0;
if (m_buffer.GetCount() + lDistanceToMove < 0)
goto clean0;
m_dwCurrentPos = (DWORD)m_buffer.GetCount() + lDistanceToMove;
}
else if (FILE_BEGIN == dwMoveMethod)
{
if (lDistanceToMove < 0)
goto clean0;
if (lDistanceToMove >= m_buffer.GetCount())
goto clean0;
m_dwCurrentPos = lDistanceToMove;
}
clean0:
return m_dwCurrentPos;
}
BOOL MemFile::CloseHandle()
{
return TRUE;
}
本文介绍了一个从内存中的zip文件解压缩的C++实现,通过定义zlib_filefunc_def结构体并自定义相关函数,配合unzOpen2使用,实现对内存中的zip文件进行解压,并将文件写入到指定目录。
2227

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



