最近项目有个关于文件压缩与解压缩的需求,网上找了一大圈发现bit7z这个开源库用的比较多,主要是开源免费,而且还比较好用。
网上找了一圈关于压缩和解压缩的代码实现的比较多,但是大部分是不能直接拿来用的,都需要或多或少需要修改一点。我这里就参考了两位博主的代码,在这两位博主的基础上修改了代码,实现通用的C++,只要求C++版本大于等于17,如果是C++11的话需要修改一点关于C++对文件的操作的代码。
至于环境搭建还有如何引用库,可以参考下面参考文章,我这里就主要是贴代码了。上github如果不太方便的话,gitee有镜像可以从gitee下载,这里注意一点,我尝试bit7z版本是3.2版本,这个版本和4.0不太一样。4.0感觉有点新,我尝试了一下,失败了。没有细研究。如果就是简单用的话建议3.2版本的bit7z。
头文件:
#pragma once
#ifndef NIMO_OBS_ZLIB_H
#define NIMO_OBS_ZLIB_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
class ZlibHelper
{
private:
uint64_t mSize;
typedef std::function UnZipProcessCallback;
typedef std::function UnZipFileCallback;
UnZipProcessCallback upc;
UnZipFileCallback ufc;
public:
ZlibHelper();
~ZlibHelper();
void Compress(const std::string& Src, const std::string& Dest, const std::string& Password = ""); // 压缩
void Extract(const std::string& Src, const std::string& Dest, const std::string& Password = ""); // 解压
void SetUnZipProcessCallback(UnZipProcessCallback upc);
void SetUnZipFileCallback(UnZipFileCallback ufc);
private:
void GetSizeOfZipPackage(const std::string& Src);
void ProcessCallback(uint64_t size);
void FileCallback(std::wstring filename);
std::wstring toWstring(const std::string& input);
std::string toString(const std::wstring& input);
};
#endif
源文件
#include "ZipHelper.h"
ZlibHelper::ZlibHelper(){}
ZlibHelper::~ZlibHelper(){}
// 压缩
void ZlibHelper::Compress(const std::string& Src, const std::string& Dest, const std::string& Password)
{
std::string::size_type iPos = (Dest.find_last_of('\\') + 1) == 0 ? Dest.find_last_of('/') + 1 : Dest.find_last_of('\\') + 1;
std::filesystem::path filePath = Dest.substr(0, iPos); // 获取文件路径
std::string fileSuffix = Dest.substr(Dest.rfind(".") + 1, Dest.size()); // 获取文件类型
bit7z::Bit7zLibrary lib(L"7z.dll");
std::shared_ptr m_pCompressor = nullptr;
if (fileSuffix == "7z")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::SevenZip);
}
else if (fileSuffix == "zip")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::Zip);
}
else if (fileSuffix == "bz2")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::BZip2);
}
else if (fileSuffix == "xz")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::Xz);
}
else if (fileSuffix == "wim")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::Wim);
}
else if (fileSuffix == "tar")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::Tar);
}
else if (fileSuffix == "gz")
{
m_pCompressor = std::make_shared(lib, bit7z::BitFormat::GZip);
}
else
{
m_pCompressor = nullptr;
return;
}
try {
// 检查是否存在这个文件夹,不存在新建
create_directories(filePath); // c++ 17 起
bit7z::ProgressCallback pc = std::bind(&ZlibHelper::ProcessCallback, this, std::placeholders::_1);
bit7z::FileCallback fc = std::bind(&ZlibHelper::FileCallback, this, std::placeholders::_1);
m_pCompressor->setProgressCallback(pc);
m_pCompressor->setFileCallback(fc);
std::wstring msSourcePath = toWstring(Src);
std::wstring msDestDir = toWstring(Dest);
std::wstring msPassword = toWstring(Password);
m_pCompressor->setPassword(msPassword);
m_pCompressor->compressDirectory(msSourcePath, msDestDir);
m_pCompressor->setUpdateMode(true);
}
catch (const bit7z::BitException& ex) {
std::cout << ex.what() << std::endl;
}
}
// 获取Zip包的大小
void ZlibHelper::GetSizeOfZipPackage(const std::string& Src)
{
std::wstring src = toWstring(Src);
bit7z::Bit7zLibrary lib(L"7z.dll");
bit7z::BitArchiveInfo info(lib, src, bit7z::BitFormat::SevenZip);
mSize = info.size();
}
void ZlibHelper::ProcessCallback(uint64_t size)
{
double process = ((1.0 * size) / mSize);
//std::wcout << process << "%" << std::endl;
if (upc) {
upc(process);
}
}
void ZlibHelper::FileCallback(std::wstring filename)
{
std::string temp = toString(filename);
//std::cout << temp.c_str() << std::endl;
if (ufc) {
ufc(temp);
}
}
// 解压
void ZlibHelper::Extract(const std::string& Src, const std::string& Dest, const std::string& Password)
{
std::string fileSuffix = Src.substr(Src.rfind(".") + 1, Src.size());
bit7z::Bit7zLibrary lib(L"7z.dll");
std::shared_ptr m_pExtractor = nullptr;
// 检查是否存在这个文件夹,不存在新建
create_directories(std::filesystem::path(Dest)); // c++ 17 起
if (fileSuffix == "7z")
{
//后缀L".7z"
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::SevenZip);
}
else if (fileSuffix == "zip")
{
//后缀L".zip"
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::Zip);
}
else if (fileSuffix == "rar")
{
//后缀L".rar"
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::Rar5);
}
else if (fileSuffix == "bz2")
{
//后缀L".bz2
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::BZip2);
}
else if (fileSuffix == "xz")
{
//后缀L".xz
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::Xz);
}
else if (fileSuffix == "wim")
{
//后缀L".wim
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::Wim);
}
else if (fileSuffix == "tar")
{
//后缀L".tar
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::Tar);
}
else if (fileSuffix == "gz")
{
//后缀L".gz
m_pExtractor = std::make_shared(lib, bit7z::BitFormat::GZip);
}
else
{
m_pExtractor = nullptr;
return;
}
try {
bit7z::ProgressCallback pc = std::bind(&ZlibHelper::ProcessCallback, this, std::placeholders::_1);
bit7z::FileCallback fc = std::bind(&ZlibHelper::FileCallback, this, std::placeholders::_1);
m_pExtractor->setProgressCallback(pc);
m_pExtractor->setFileCallback(fc);
std::wstring msSourcePath = toWstring(Src);
std::wstring msDestDir = toWstring(Dest);
std::wstring msPassword = toWstring(Password);
m_pExtractor->setPassword(msPassword);
m_pExtractor->extract(msSourcePath, msDestDir);
}
catch (const bit7z::BitException& ex) {
std::cout << ex.what() << std::endl;
}
}
void ZlibHelper::SetUnZipProcessCallback(UnZipProcessCallback upc)
{
this->upc = upc;
}
void ZlibHelper::SetUnZipFileCallback(UnZipFileCallback ufc)
{
this->ufc = ufc;
}
//convert string to wstring
std::wstring ZlibHelper::toWstring(const std::string& input)
{
std::wstring_convert> converter;
return converter.from_bytes(input);
}
//convert wstring to string
std::string ZlibHelper::toString(const std::wstring& input)
{
std::wstring_convert> converter;
return converter.to_bytes(input);
}
测试代码:
#include "ZipHelper.h"
int main()
{
//std::string src = "F:/code/console/Use7z/data/qwe/asd/zxc/123.7z";
std::string src = "F:/code/console/Use7z/data/123.7z";
std::string dist = "F:\\code\\console\\Use7z\\data\\out\\asd\\zxc\\123\\";
ZlibHelper* pUnzip = new ZlibHelper();
pUnzip->Extract(src, dist);
//pUnzip->Compress(dist, src);
return 0;
}
我自己写的demo资源。
use7z的demo,里面主要简单封装了一个压缩和解压缩的函数资源-CSDN文库
参考文章:
C++解压库bit7z编译以及使用-CSDN博客
C++ 调用7z进行解压缩,并返回解压缩进度和异常信息_7z.dll调用-CSDN博客
C++ string获取文件路径文件名、文件路径、文件后缀(两种方式)_string 路径-CSDN博客
std::filesystem::create_directory, std::filesystem::create_directories - C++中文 - API参考文档 (apiref.com) C++11文件目录操作简介_c++ 目录操作-CSDN博客