C++ 解压文件及文件夹 使用zlib开源库

C++ 解压文件及文件夹 使用zlib开源库

  使用zlib-1.2.11版本的开源库,实现我需要的对文件或者文件夹的解压,查阅了一些博客大牛的资料,后面根据自己的需要修改。这是续上一篇的压缩,好久了都忘记这回事了。下面给出我的代码:

#include "stdafx.h"
#include <string>
#include <iostream>
#include <vector>
#include <Shlwapi.h> 
#include "zip.h"
#include "unzip.h"
#include "zlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <sstream>

using namespace std;

#pragma comment(lib, "Shlwapi.lib")

//主要的解压函数
void UnzipFile(const std::string& strFilePath, const std::string& strTempPath);
//额外处理函数
std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value);
BOOL CreatedMultipleDirectory(const std::string& direct);

int _tmain(int argc, _TCHAR* argv[])
{
 	std::string srcFilePath = "C:\\TDDownload\\mysql\\mysql-5.5.19-win32.zip";
 	std::string tempdir = "D:\\Mytest\\server\\temp";
 	if (!::PathFileExistsA(tempdir.c_str()))
 	{
 		CreatedMultipleDirectory(tempdir);
 	}
 	UnzipFile(srcFilePath , tempdir);

	system("pause");
	return 0;
}


void UnzipFile(const std::string& strFilePath, const std::string& strTempPath)
{
	int nReturnValue;
	string tempFilePath;
	string srcFilePath(strFilePath);
	string destFilePath;

	std::cout << "Start unpacking the package... " << endl;

	//打开zip文件
	unzFile unzfile = unzOpen(srcFilePath.c_str());
	if (unzfile == NULL)
	{
		return;
	}

	//获取zip文件的信息
	unz_global_info* pGlobalInfo = new unz_global_info;
	nReturnValue = unzGetGlobalInfo(unzfile, pGlobalInfo);
	if (nReturnValue != UNZ_OK)
	{
		std::cout << "The number of compressed package files is  " << pGlobalInfo->number_entry << endl;
		return;
	}


	//解析zip文件
	unz_file_info* pFileInfo = new unz_file_info;
	char szZipFName[MAX_PATH] = { 0 };
	char szExtraName[MAX_PATH] = { 0 };
	char szCommName[MAX_PATH] = { 0 };
	//存放从zip中解析出来的内部文件名
	for (int i = 0; i < pGlobalInfo->number_entry; i++)
	{
		//解析得到zip中的文件信息
		nReturnValue = unzGetCurrentFileInfo(unzfile, pFileInfo, szZipFName, MAX_PATH, szExtraName, MAX_PATH, szCommName, MAX_PATH);
		if (nReturnValue != UNZ_OK)
			return;
		std::cout << "ZipName: " << szZipFName << "Extra: " << szExtraName << "Comm: " << szCommName << endl;

		string strZipFName = szZipFName;
		if (pFileInfo->external_fa == FILE_ATTRIBUTE_DIRECTORY || (strZipFName.rfind('/') == strZipFName.length() - 1))
		{
			destFilePath = strTempPath + "//" + szZipFName;
			CreateDirectoryA(destFilePath.c_str(), NULL);
		}
		else
		{
			//创建文件
			string strFullFilePath;
			tempFilePath = strTempPath + "/" + szZipFName;
			strFullFilePath = tempFilePath;//保存完整路径

			int nPos = tempFilePath.rfind("/");
			int nPosRev = tempFilePath.rfind("\\");
			if (nPosRev == string::npos && nPos == string::npos)
				continue;

			size_t nSplitPos = nPos > nPosRev ? nPos : nPosRev;
			destFilePath = tempFilePath.substr(0, nSplitPos + 1);

			if (!PathIsDirectoryA(destFilePath.c_str()))
			{
				//将路径格式统一
				destFilePath = replace_all(destFilePath, "/", "\\");
				//创建多级目录
				int bRet = CreatedMultipleDirectory(destFilePath);
			}
			strFullFilePath = replace_all(strFullFilePath, "/", "\\");

			HANDLE hFile = CreateFileA(strFullFilePath.c_str(), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
			if (hFile == INVALID_HANDLE_VALUE)
			{
				return;
			}

			//打开文件
			nReturnValue = unzOpenCurrentFile(unzfile);
			if (nReturnValue != UNZ_OK)
			{
				CloseHandle(hFile);
				return;
			}

			//读取文件
			uLong BUFFER_SIZE = pFileInfo->uncompressed_size;;
			void* szReadBuffer = NULL;
			szReadBuffer = (char*)malloc(BUFFER_SIZE);
			if (NULL == szReadBuffer)
			{
				break;
			}

			while (TRUE)
			{
				memset(szReadBuffer, 0, BUFFER_SIZE);
				int nReadFileSize = 0;

				nReadFileSize = unzReadCurrentFile(unzfile, szReadBuffer, BUFFER_SIZE);

				if (nReadFileSize < 0)					 //读取文件失败
				{
					unzCloseCurrentFile(unzfile);
					CloseHandle(hFile);
					return;
				}
				else if (nReadFileSize == 0)           //读取文件完毕
				{	
					unzCloseCurrentFile(unzfile);
					CloseHandle(hFile);
					break;
				}
				else									//写入读取的内容
				{
					DWORD dWrite = 0;
					BOOL bWriteSuccessed = WriteFile(hFile, szReadBuffer, BUFFER_SIZE, &dWrite, NULL);
					if (!bWriteSuccessed)
					{
						unzCloseCurrentFile(unzfile);
						CloseHandle(hFile);
						return;
					}
				}
			}

			free(szReadBuffer);
		}
		unzGoToNextFile(unzfile);
	}

	delete pFileInfo;

	delete pGlobalInfo;

	//关闭
	if (unzfile)
	{
		unzClose(unzfile);
	}
	std::cout << "End unpacking the package... " << endl;
}

std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
{
	while (true)
	{
		std::string::size_type   pos(0);
		if ((pos = str.find(old_value)) != std::string::npos)
			str.replace(pos, old_value.length(), new_value);
		else
			break;
	}
	return str;
}


BOOL CreatedMultipleDirectory(const std::string& direct)
{
	std::string Directoryname = direct;
	if (Directoryname[Directoryname.length() - 1] != '\\')
	{
		Directoryname.append(1, '\\');
	}
	std::vector< std::string> vpath;
	std::string strtemp;
	BOOL  bSuccess = FALSE;
	for (int i = 0; i < Directoryname.length(); i++)
	{
		if (Directoryname[i] != '\\')
		{
			strtemp.append(1, Directoryname[i]);
		}
		else
		{
			vpath.push_back(strtemp);
			strtemp.append(1, '\\');
		}
	}
	std::vector< std::string>::iterator vIter = vpath.begin();
	for (; vIter != vpath.end(); vIter++)
	{
		bSuccess = CreateDirectoryA(vIter->c_str(), NULL) ? TRUE : FALSE;
	}
	return bSuccess;
}

zlib库自行下载来编译,然后加入到自己的项目里面去,(需要重新编译哦,不顺利的话可能会遇到很多问题哦x_O)。在下刚出自茅庐,不足之处还望指教,相互学习。基本上对文件的压缩解压,这两篇文章已经能够满足了,但是对于压缩解压的实时进度,那就需要自己实现该。似乎zlib没有提供回调进度(不知道是我还没发现还是真实没有?)。进度这一块虽然已经实现了,但是对单个文件的进度处理还有些问题。zlib也支持.rar的压缩解压,之前试过,具体不大记得了。后续再上传demo吧!

    原文作者:sadwjy520
    原文地址: https://blog.csdn.net/sadwjy520/article/details/81502434
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞