最近项目有个关于文件压缩与解压缩的需求,网上找了一大圈发现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<void(double process)> UnZipProcessCallback;
- typedef std::function<void(std::string filename)> 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
wchar_t>> converter; - return converter.from_bytes(input);
- }
-
- //convert wstring to string
- std::string ZlibHelper::toString(const std::wstring& input)
- {
- std::wstring_convert
wchar_t>> 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文库
--------------20231008-------------------------------
基于上面函数我修改了一点
头文件
- #pragma once
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #if _MSC_VER >= 1910
- using Path = std::filesystem::path;
- using DirIter = std::filesystem::directory_iterator;
- #elif _MSC_VER >= 1900
- using Path = std::tr2::sys::path;
- using DirIter = std::tr2::sys::directory_iterator;
- #endif
-
- class ZlibHelper
- {
- private:
- uint64_t mSize;
- typedef std::function<void(double process)> UnZipProcessCallback;
- typedef std::function<void(std::string filename)> UnZipFileCallback;
- UnZipProcessCallback upc;
- UnZipFileCallback ufc;
- public:
- ZlibHelper();
- ~ZlibHelper();
-
- void Compress(const std::string& Src, const std::string& Dest, bool IsdeleteSourceFile = false, const std::string& Password = ""); // 压缩
- void Extract(const std::string& Src, const std::string& Dest, bool IsdeleteSourceFile = false, const std::string& Password = ""); // 解压
- void SetUnZipProcessCallback(UnZipProcessCallback upc);
- void SetUnZipFileCallback(UnZipFileCallback ufc);
- private:
- void test(); // 使用 ZlibHelper demo
- uint64_t GetSizeOfFolder(const std::string& src); // 获得字节数
- 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);
-
- private:
- bool m_bIsdeleteSourceFile = false;
- std::string m_CompressFolderPath = "";
- std::map
m_ZlibFormat; - };
-
源文件:
- #include "ZlibHelper.h"
-
-
- ZlibHelper::ZlibHelper()
- {
- m_ZlibFormat["7z"] = const_cast
(&bit7z::BitFormat::SevenZip); - m_ZlibFormat["zip"] = const_cast
(&bit7z::BitFormat::Zip); - m_ZlibFormat["bz2"] = const_cast
(&bit7z::BitFormat::BZip2); - m_ZlibFormat["xz"] = const_cast
(&bit7z::BitFormat::Xz); - m_ZlibFormat["wim"] = const_cast
(&bit7z::BitFormat::Wim); - m_ZlibFormat["tar"] = const_cast
(&bit7z::BitFormat::Tar); - m_ZlibFormat["gz"] = const_cast
(&bit7z::BitFormat::GZip); - }
-
- ZlibHelper::~ZlibHelper() {}
-
- // 压缩
- void ZlibHelper::Compress(const std::string& Src, const std::string& Dest, bool IsdeleteSourceFile, const std::string& Password)
- {
- m_CompressFolderPath = Src;
- m_bIsdeleteSourceFile = IsdeleteSourceFile;
- mSize = GetSizeOfFolder(m_CompressFolderPath);
- std::string::size_type iPos = (Dest.find_last_of('\\') + 1) == 0 ? Dest.find_last_of('/') + 1 : Dest.find_last_of('\\') + 1;
- Path filePath = Dest.substr(0, iPos); // C++ 11 获取文件路径
- std::string fileSuffix = Dest.substr(Dest.rfind(".") + 1, Dest.size()); // 获取文件类型
- bit7z::Bit7zLibrary lib(L"7z.dll");
- try {
- std::shared_ptr
m_pCompressor = std::make_shared(lib, *(m_ZlibFormat[fileSuffix])); - create_directories(filePath); // 检查是否存在这个文件夹,不存在新建
- 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;
- }
- }
-
- // 解压
- void ZlibHelper::Extract(const std::string& Src, const std::string& Dest, bool IsdeleteSourceFile, const std::string& Password)
- {
- m_bIsdeleteSourceFile = IsdeleteSourceFile;
- std::string fileSuffix = Src.substr(Src.rfind(".") + 1, Src.size());
- bit7z::Bit7zLibrary lib(L"7z.dll");
- // 检查是否存在这个文件夹,不存在新建
- create_directories(Path(Dest)); // c++ 11
- try
- {
- std::shared_ptr
m_pExtractor = std::make_shared(lib, *(m_ZlibFormat[fileSuffix])); - 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::test()
- {
- //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);
- }
-
- uint64_t ZlibHelper::GetSizeOfFolder(const std::string& src)
- {
-
- uint64_t lFolderSize = 0;
- Path src_dir(src);
- for (DirIter end, ite(src_dir); ite != end; ++ite)
- {
- if (!is_directory(ite->path()))
- {
- lFolderSize += file_size(Path(src + "\\" + ite->path().filename().string()));
- }
- };
- return lFolderSize;
- }
-
- // 获取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 = ((100.0 * size) / mSize);
- if (upc) {
- upc(process);
- }
- if (process == 100 && m_bIsdeleteSourceFile) // 压缩完删除源文件
- {
- remove_all(Path(m_CompressFolderPath));
- }
- }
-
- void ZlibHelper::FileCallback(std::wstring filename)
- {
- std::string temp = toString(filename);
- //std::cout << temp.c_str() << std::endl;
- if (ufc) {
- ufc(temp);
- }
- }
-
-
- 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
wchar_t>> converter; - return converter.from_bytes(input);
- }
-
- //convert wstring to string
- std::string ZlibHelper::toString(const std::wstring& input)
- {
- std::wstring_convert
wchar_t>> converter; - return converter.to_bytes(input);
- }
参考文章:
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博客