C++实现解zip解压缩功能:将一个目录内的内容打包到zip文件以及将zip文件解压到某个目录(windows平台)

本例用来简单实现windows平台下如何将一个目录下的文件压缩到指定的zip文件中,亦或是将一个zip文件的内容解压缩到某个目录。

 

以下是源码,代码中的注释解释了相关操作,一看就懂

 

注:

本例将这两个功能封装在了一个叫ZipPack的命名空间中。

代码中使用到的zip.h zip.cpp unzip.h unzip.cpp可以从www.info-zip.org下载。同时我也提供了具体的代码示例:点击下载

 

.h

#pragma once
#include <iostream>

namespace ZipPack
{
	//* 遍历文件夹下的所有文件到zip
	//targetPath: 起始目录
	//currentDir: 当前遍历所处的目录
	//hZip: HZIP 句柄地址
	void BrowseFileToZip(std::wstring targetDir, std::wstring currentDir, void* hZip);

	//* 将目录打包为zip
	//targetPath: 要打包的目录
	//dstZip: 打包之后的zip文件位置
	bool PackDirToZip(std::wstring targetDir, std::wstring dstZip);

	//* 将zip文件解压到对应的目录
	//targetZip:需要解压的文件
	//dstPath:解压之后的文件所在目录(如果目录内已存在相同文件则会覆盖)
	bool UnPackZipToDir(std::wstring targetZip, std::wstring dstPath, std::string psw="");
};

.cpp

#include "ZipPack.h"
#include <windows.h>
#include <Shlwapi.h>
#include "zip.h"
#include "unzip.h"

#pragma comment(lib, "shlwapi.lib")  //Windows API   PathFileExists

bool ZipPack::PackDirToZip( std::wstring targetDir, std::wstring dstZip )
{
	//用于输出调试信息
	std::wstring dbgInfo;
	dbgInfo.resize(MAX_PATH);

	if(targetDir.empty() || dstZip.empty())
	{
		wsprintfW(&dbgInfo[0], L"failed: empty path.");
		OutputDebugStringW(dbgInfo.c_str());
		return false;
	}

	//检查目标路径是否有效
	BOOL bTargetPathExists = ::PathFileExistsW(targetDir.c_str());
	if(!bTargetPathExists)
	{
		wsprintfW(&dbgInfo[0], L"failed: invalid path(%s).", targetDir.c_str());
		OutputDebugStringW(dbgInfo.c_str());
		return false;
	}

	//创建HZIP, 这里默认不设置密码,如有需要可传入密码参数
	HZIP hZip = CreateZip(dstZip.c_str(), 0);
	if(!IsZipHandleZ(hZip))
	{
		wsprintfW(&dbgInfo[0], L"failed: create zip file(%s) failed.", dstZip.c_str());
		OutputDebugStringW(dbgInfo.c_str());
		return false;
	}
	//* 将目录下的所有子文件夹和子文件加入zip文件中
	BrowseFileToZip(targetDir, targetDir, &hZip);

	CloseZip(hZip);

	return true;
}

void ZipPack::BrowseFileToZip(std::wstring targetDir, std::wstring currentDir, void* hZip)
{
	HZIP* pHZip = (HZIP*)hZip;

	//用于输出调试信息
	std::wstring dbgInfo;
	dbgInfo.resize(MAX_PATH);
	
	WIN32_FIND_DATA FindFileData;
    HANDLE hListFile;
    WCHAR szFilePath[MAX_PATH];

    // 构造代表子目录和文件夹路径的字符串,使用通配符"*"
    lstrcpy(szFilePath, currentDir.c_str());
    // 注释的代码可以用于查找所有以“.txt”结尾的文件
    // lstrcat(szFilePath, "\\*.txt");
    lstrcat(szFilePath, L"\\*");

    // 查找第一个文件/目录,获得查找句柄
    hListFile = FindFirstFile(szFilePath, &FindFileData);
    // 判断句柄
    if(hListFile == INVALID_HANDLE_VALUE)
    {
        wsprintfW(&dbgInfo[0], L"BrowseFileToZip Error:%d\n", GetLastError());
		OutputDebugStringW(dbgInfo.c_str());
        return ;
    }
    else
    {
        do
        {
            //如果不想显示代表本级目录和上级目录的“.”和“..”,
			//可以使用注释部分的代码过滤
			if(lstrcmp(FindFileData.cFileName, TEXT(".")) == 0 ||
			lstrcmp(FindFileData.cFileName, TEXT("..")) == 0)
			{
				continue;
			}
			

            // 打印文件名、目录名
            wsprintfW(&dbgInfo[0], L"%ws\t\t", FindFileData.cFileName);
			OutputDebugStringW(dbgInfo.c_str());

            // 判断文件属性,是否为加密文件或者文件夹
            if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED)
            {
                wsprintfW(&dbgInfo[0], L"<加密> ");
				OutputDebugStringW(dbgInfo.c_str());
            }
            // 判断文件属性,是否为隐藏文件或文件夹
            if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
            {
                wsprintfW(&dbgInfo[0], L"<隐藏> ");
				OutputDebugStringW(dbgInfo.c_str());
            }
            // 判断文件属性,是否为目录
            if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                wsprintfW(&dbgInfo[0], L"<DIR> ");
				OutputDebugStringW(dbgInfo.c_str());

				//子文件夹的绝对路径
				std::wstring absSubDir = currentDir;
				absSubDir.append(L"\\");
				absSubDir.append(FindFileData.cFileName);
				
				//子文件夹的相对路径
				std::wstring tSubDir = absSubDir.substr(targetDir.length() + 1, absSubDir.length() - targetDir.length());

				//将文件夹添加到ZIP文件
				ZipAddFolder(*pHZip,tSubDir.c_str());

				//遍历子文件夹
				BrowseFileToZip(targetDir, absSubDir, pHZip);
            }
			else //*不是目录的当文件处理
			{
				//子文件的绝对路径
				std::wstring absSubDir = currentDir;
				absSubDir.append(L"\\");
				absSubDir.append(FindFileData.cFileName);

				//子文件的相对路径
				std::wstring tSubDir = absSubDir.substr(targetDir.length() + 1, absSubDir.length() - targetDir.length());

				ZipAdd(*pHZip,tSubDir.c_str(),absSubDir.c_str());
			}

            // 读者可根据文件属性表中的内容自行添加、判断文件属性
            wsprintfW(&dbgInfo[0], L"\n");
			OutputDebugStringW(dbgInfo.c_str());
        }
        while(FindNextFile(hListFile, &FindFileData));
    }

}

bool ZipPack::UnPackZipToDir(std::wstring targetZip, std::wstring dstPath, std::string psw)
{
	//用于输出调试信息
	std::wstring dbgInfo;
	dbgInfo.resize(MAX_PATH);

	if(!::PathFileExistsW(targetZip.c_str()) || !PathFileExistsW(dstPath.c_str()))
	{
		wsprintfW(&dbgInfo[0], L"UnPackZipToPath failed, invalid file or dir");
		OutputDebugStringW(dbgInfo.c_str());
		return false;
	}

	HZIP hz = OpenZip(&targetZip[0], psw.c_str());
	if(hz == NULL)
	{
		wsprintfW(&dbgInfo[0], L"UnPackZipToPath failed, open zip(%s) failed", targetZip.c_str());
		OutputDebugStringW(dbgInfo.c_str());
		return false;
	}
	bool bRtn;
	bRtn = true;
	ZRESULT zRtn;
	zRtn = SetUnzipBaseDir(hz, dstPath.c_str());
	if(zRtn == ZR_OK)
	{
		ZIPENTRY ze;
		zRtn = GetZipItem(hz,-1,&ze); 
		if(zRtn == ZR_OK)
		{
			int numitems = ze.index;
			for(int zi=0; zi<numitems; zi++)
			{ 
				ZIPENTRY zetmp; 
				zRtn = GetZipItem(hz, zi, &zetmp);
				if(zRtn != ZR_OK)
				{
					bRtn = false;
				}
				zRtn = UnzipItem(hz, zi, zetmp.name);
				if(zRtn != ZR_OK)
				{
					//如果外边是只读文件,那么就不处理
					//bRtn = false;
					switch(zRtn)
					{
					case ZR_NOFILE:
					case ZR_NODUPH:
					case ZR_NOALLOC:
					case ZR_WRITE:
						break;
					default:
						bRtn = false;
						break;
					}
				}
			}
		}
		else
		{
			bRtn = false;
		}
	}
	else
	{
		bRtn = false;
	}
	CloseZip(hz);

	wsprintfW(&dbgInfo[0], L"UnPackZipToPath, success(%d)", bRtn);
	OutputDebugStringW(dbgInfo.c_str());
	return bRtn;
}

 

使用示例:

#include "ZipPack.h"


int main(int argc, char** argv)
{
	ZipPack::PackDirToZip(L"F:\\WorkSpace2.0\\VSProject\\WindowsProject1",L"F:\\WorkSpace2.0\\VSProject\\ZipPack\\test.zip");
	ZipPack::UnPackZipToDir(L"F:\\WorkSpace2.0\\VSProject\\ZipPack\\test.zip", L"F:\\WorkSpace2.0\\VSProject\\ZipPack\\UNPACK");
	return 0;
}

运行之后就能看到打包的zip文件也解压之后的文件了。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用C++的tar库来压缩多个文件一个tar文件中。以下是一个简单的示例代码,可以将多个文件打包一个tar文件: ```c++ #include <iostream> #include <fstream> #include <string> #include <vector> #include <archive.h> #include <archive_entry.h> int main(int argc, char** argv) { // 检查参数是否正确 if (argc < 3) { std::cerr << "Usage: " << argv[0] << " <output_tar_file> <input_file_1> [<input_file_2> ...]" << std::endl; return 1; } // 打开tar文件 std::string tar_filename(argv[1]); struct archive* tar = archive_write_new(); archive_write_set_format_pax_restricted(tar); archive_write_open_filename(tar, tar_filename.c_str()); // 添加输入文件到tar文件中 for (int i = 2; i < argc; i++) { std::string input_filename(argv[i]); // 获取文件信息 struct archive_entry* entry = archive_entry_new(); archive_entry_clear(entry); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_pathname(entry, input_filename.c_str()); archive_entry_set_size(entry, -1); // 打开输入文件 std::ifstream input_file(input_filename, std::ios::binary); if (!input_file.is_open()) { std::cerr << "Failed to open input file: " << input_filename << std::endl; return 1; } // 将文件写入tar文件 archive_write_header(tar, entry); char buffer[4096]; while (input_file.read(buffer, sizeof(buffer)).gcount() > 0) { archive_write_data(tar, buffer, input_file.gcount()); } // 关闭输入文件 input_file.close(); archive_entry_free(entry); } // 关闭tar文件 archive_write_close(tar); archive_write_free(tar); return 0; } ``` 你可以将多个输入文件作为参数传递给该程序,例如: ``` ./compress_file my_archive.tar file1.txt file2.txt file3.txt ``` 该程序将创建一个名为`my_archive.tar`的tar文件,并将`file1.txt`、`file2.txt`和`file3.txt`添加到其中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值