c++實(shí)現(xiàn)解析zip文件的示例代碼
libzip
官網(wǎng)地址:
示例代碼
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <zip.h>
//解析原始zip內(nèi)容,保存為新的zip文件
int ziptest(const char* inputPath, const char* outputPath)
{
int error = 0;
zip_t *zip_file = zip_open(inputPath, ZIP_CHECKCONS, &error);
if (zip_file == NULL) {
printf("Failed to open zip file: %s\n", zip_strerror(zip_file));
return 1;
}
// 獲取條目數(shù)量
int numEntries = zip_get_num_entries(zip_file, 0);
if (numEntries < 0) {
std::cerr << "Failed to get number of entries." << std::endl;
zip_close(zip_file);
return 1;
}
//保存為目標(biāo)zip文件
zip_t* archive = zip_open(outputPath, ZIP_CREATE | ZIP_TRUNCATE, nullptr);
if (archive == nullptr) {
std::cout << "無(wú)法創(chuàng)建 ZIP 存檔." << std::endl;
return 1;
}
unsigned char* itemData = NULL;
for (size_t i = 0; i < numEntries; i++) {
zip_stat_t entryStat;
if (zip_stat_index(zip_file, i, 0, &entryStat) != 0) {
std::cerr << "Failed to get information for entry " << i << std::endl;
continue;
}
//printf("index: [%llu]\t", entryStat.index);
//printf("Name: [%s]\t", entryStat.name);
//printf("valid: [%llu]\t", entryStat.valid);
//printf("Size: [%llu]\t", entryStat.size);
//printf("comp_size: [%llu]\t", entryStat.comp_size);
//printf("comp_method: [%zu]", entryStat.comp_method);
//printf("\t flags: [%lu]\n", entryStat.flags);
if (entryStat.valid & ZIP_STAT_NAME) {
// 打開條目文件
zip_file_t *entryFile = zip_fopen_index(zip_file, i, 0);
if (entryFile == NULL) {
std::cerr << "Failed to open entry file: " << entryStat.name << std::endl;
//goto END;
continue;
}
size_t bufferSize = entryStat.size;
// 讀取內(nèi)存空間
itemData = (unsigned char *)malloc(bufferSize);
if (zip_fread(entryFile, itemData, bufferSize) < 0) {
std::cerr << "Failed to read entry file: " << entryStat.name << std::endl;
zip_fclose(entryFile);
if (itemData != NULL) {
free(itemData);
itemData = NULL;
}
continue;
}
// 創(chuàng)建源對(duì)象,并將其添加到 ZIP 存檔中
//zip_source_buffer內(nèi)部會(huì)自動(dòng)釋放itemData內(nèi)存
zip_source* source = zip_source_buffer(archive, itemData, bufferSize, 0);
if (source == NULL) {
std::cout << "無(wú)法寫入 ZIP 文件." << std::endl;
if (itemData != NULL) {
free(itemData);
itemData = NULL;
}
zip_fclose(entryFile);
continue;
}
// use zip_file_replace() to modify source zip file
/****
if (zip_file_replace(zip_file, i, source, 0) < 0) {
std::cout << "replace failed." << std::endl;
zip_source_free(source);
zip_fclose(entryFile);
break;
}
****/
if (zip_file_add(archive, entryStat.name, source, ZIP_FL_OVERWRITE) < 0) {
std::cout << "無(wú)法寫入 ZIP 文件." << std::endl;
zip_source_free(source);
zip_fclose(entryFile);
if (itemData != NULL) {
free(itemData);
itemData = NULL;
}
continue;
}
zip_fclose(entryFile);
}
}
// 關(guān)閉zip文件
zip_close(zip_file);
zip_close(archive);
return 0;
}
#include <zip.h>
#include <memory.h>
#include <stdio.h>
#include <math.h>
#include <fstream>
#ifdef _WIN32
#include <io.h> /* _access */
#include<direct.h> /* _mkdir */
#include<windows.h>
#else
#include<unistd.h> /* access */
#include<sys/stat.h> /*mkdir*/
#include <sys/types.h>
#endif
//創(chuàng)建多級(jí)文件夾
void createFolders(std::string rootPath);
//獲取多級(jí)文件夾下所以文件列表
void getDirAllFilePath(const char* folderPath, std::vector<std::string>& filePaths);
//解壓zip,保存到磁盤指定目錄
int unzipFunc(const char* destzip, const std::string output) {
// 打開ZIP文件
zip* archive = zip_open(destzip , 0, NULL);
if (!archive) {
std::cerr << "Failed to open archive" << std::endl;
return -1;
}
// 獲取ZIP文件中的文件數(shù)量
int numFiles = zip_get_num_files(archive);
//std::cout << "Archive contains " << numFiles << " files" << std::endl;
// 遍歷ZIP文件中的所有文件
for (int i = 0; i < numFiles; ++i) {
FILE *fp = NULL;
// 獲取文件的名稱和大小
zip_stat_t fileStat;
zip_stat_init(&fileStat);
if (zip_stat_index(archive, i, 0, &fileStat) != 0) {
std::cerr << "Failed to get file info for index " << i << std::endl;
continue;
}
int len = strlen(fileStat.name);
std::cout << "File " << i << ": " << fileStat.name << " (" << fileStat.size << " bytes)" << std::endl;
// 解壓文件到磁盤指定位置, 執(zhí)行解壓之前, 需創(chuàng)建對(duì)應(yīng)的文件夾,否則,解壓失敗
std::string dest_name = output + std::string(fileStat.name);
createFolders(dest_name);
zip_file_t* zf = zip_fopen_index(archive, i, 0);
if (!zf) {
continue;
}
fp = fopen(dest_name.c_str(), "wb");
if (fp == NULL) { continue; }
long long sum = 0;
unsigned char* buffer = (unsigned char*)malloc(fileStat.size);
memset(buffer, 0, fileStat.size);
if (zip_fread(zf, buffer, fileStat.size) < 0) {
continue;
}
fwrite(buffer, 1, fileStat.size, fp);
free(buffer);
buffer = NULL;
zip_fclose(zf);
fclose(fp);
}
// 關(guān)閉ZIP文件
if (zip_close(archive) != 0) {
std::cerr << "Failed to close archive" << std::endl;
return -1;
}
return 0;
}
//將文件夾壓縮為指定的zip
int zipFunc(const char* inputDirPath, const char* destzip) {
// 打開ZIP文件
int iErr = 0;
zip* archive = zip_open(destzip, ZIP_CREATE | ZIP_TRUNCATE, &iErr);
if (!archive) {
std::cerr << "Failed to open archive" << std::endl;
return -1;
}
std::vector<std::string> files;
//獲取的是絕對(duì)路徑
getDirAllFilePath(inputDirPath, files);
std::string rootPath(inputDirPath);
for (size_t i = 0; i < files.size(); i++) {
std::string::size_type rootSize = rootPath.length();
//獲取指定目錄下的相對(duì)路徑,作為zip包的條目名稱
std::string itemName = files[i].substr(rootSize + 1);
std::cout << "entry: " << files[i].c_str() << std::endl;
//通過(guò)文件創(chuàng)建zip_source源對(duì)象
zip_source_t* source = zip_source_file(archive, files[i].c_str(), 0, -1);
if (!source)
{
printf(" open zip_source file failed\n");
zip_close(archive);
return 1;
}
//add file
if (zip_file_add(archive, itemName .c_str(), source, ZIP_FL_OVERWRITE) < 0) {
zip_source_free(source);
zip_close(archive);
return 2;
}
}
// 關(guān)閉ZIP文件
if (zip_close(archive) != 0) {
std::cerr << "Failed to close archive" << std::endl;
return -1;
}
return 0;
}
//創(chuàng)建文件夾
int create_dir(const char *dir)
{
#ifdef WIN32
if ((_access(dir, 0)) != 0) //如果文件夾不存在
{
int flag = _mkdir(dir);
if (flag != 0)
{
printf("Fail to create directory %s.", dir); //"Fail to create directory." << std::endl;
return OOXML_PARAMETER_ERR;
}
}
#else
if ((access(dir, 0)) != 0) //如果文件夾不存在
{
int flag = mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
if (flag != 0)
{
printf("Fail to create directory %s.", dir);
return OOXML_PARAMETER_ERR;
}
}
#endif
return 0;
}
//遞歸創(chuàng)建文件夾
void mkdirRecursively(const std::string root, const std::string folderPath)
{
size_t pos = folderPath.find('/');
std::string subPath;
if (pos != std::string::npos)
{
subPath = folderPath.substr(0, pos);
}
else {
subPath = folderPath;
}
if (root == "") {
if (!subPath.empty())
{
if(create_dir(subPath.c_str()) != 0) return ;
std::string remainingPath = folderPath.substr(pos + 1);
if (pos != std::string::npos) {
return mkdirRecursively(subPath, remainingPath);
}
else {
return ;
}
}
}
else {
std::string subdir = root;
if (subdir.back() != '/') {
subdir += "/";
}
if (!subPath.empty()){
std::string current = subdir + subPath;
if (create_dir(current.c_str()) != 0) return ;
std::string remainingPath = folderPath.substr(pos + 1);
if (pos != std::string::npos) {
return mkdirRecursively(current, remainingPath);
}
else {
return ;
}
}
}
return ;
}
//創(chuàng)建多級(jí)文件夾
//如果是文件,則創(chuàng)建文件所占目錄文件夾
void createFolders(std::string rootPath)
{
std::string::size_type idx = rootPath.find_last_of('/');
std::string filename = rootPath.substr(idx + 1);
std::string::size_type pos = filename.find('.');
if (!filename.empty() && (pos != std::string::npos)) {
std::string subdirname = rootPath.substr(0, idx + 1);
//std::cout << subdirname << std::endl;
mkdirRecursively("", subdirname);
}
else{
//std::cout << rootPath << std::endl;
mkdirRecursively("", rootPath);
}
}
void getDirAllFilePath(const char* folderPath, std::vector<std::string>& filePaths)
{
#ifdef WIN32
HANDLE hFind;
WIN32_FIND_DATA findData;
LARGE_INTEGER size;
char dirNew[128] = { 0x0 };
// 向目錄加通配符,用于搜索第一個(gè)文件
strcpy(dirNew, folderPath);
strcat(dirNew, "\\*.*");
hFind = FindFirstFile(dirNew, &findData);
if (hFind == INVALID_HANDLE_VALUE)
{
std::cerr << "無(wú)法打開目錄:" << folderPath << std::endl;
return;
}
do
{
// 是否是文件夾,并且名稱不為"."或".."
//std::cout << findData.dwFileAttributes << "\n";
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
&& strcmp(findData.cFileName, ".") != 0
&& strcmp(findData.cFileName, "..") != 0
)
{
// 將dirNew設(shè)置為搜索到的目錄,并進(jìn)行下一輪搜索
std::string file(findData.cFileName);
std::string newPath = std::string(folderPath) + "/" + file;
getFiles(newPath.c_str(), filePaths);
}
else if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0) {
continue;
}
else {
std::string file(findData.cFileName);
std::string fullPath = std::string(folderPath) + "/" + file;
filePaths.push_back(fullPath);
}
} while (FindNextFile(hFind, &findData));
FindClose(hFind);
#else
DIR* dir = opendir(folderPath);
if (dir == nullptr)
{
std::cerr << "無(wú)法打開目錄:" << folderPath << std::endl;
return;
}
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr)
{
std::string entryName(entry->d_name);
if (entryName == "." || entryName == "..")
{
continue;
}
std::string entryPath(folderPath);
if (entryPath.back() != '/') { entryPath += "/"; }
entryPath +=entryName;
struct stat entryStat;
if (stat(entryPath.c_str(), &entryStat) == -1)
{
std::cerr << "無(wú)法獲取文件屬性:" << entryPath << std::endl;
continue;
}
if (S_ISDIR(entryStat.st_mode))
{
// 如果是子目錄,則遞歸調(diào)用該函數(shù)獲取子文件夾中的文件路徑
getFiles(entryPath.c_str(), filePaths);
}
else if (S_ISREG(entryStat.st_mode))
{
// 如果是文件,則添加到路徑列表中
filePaths.push_back(entryPath);
}
}
closedir(dir);
#endif
}
到此這篇關(guān)于c++實(shí)現(xiàn)解析zip文件的示例代碼的文章就介紹到這了,更多相關(guān)c++解析zip文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享
這篇文章主要為大家詳細(xì)介紹了Qt中實(shí)現(xiàn)定時(shí)器的兩種不同方法,文中的示例代碼講解詳細(xì),對(duì)我們了解Qt有一定的幫助,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-11-11
C語(yǔ)言輾轉(zhuǎn)相除法求2個(gè)數(shù)的最小公約數(shù)
輾轉(zhuǎn)相除法最大的用途就是用來(lái)求兩個(gè)數(shù)的最大公約數(shù)。下面通過(guò)本文給大家介紹C語(yǔ)言輾轉(zhuǎn)相除法求2個(gè)數(shù)的最小公約數(shù),非常不錯(cuò),感興趣的朋友一起看看吧2016-12-12
C語(yǔ)言運(yùn)算符深入探究?jī)?yōu)先級(jí)與結(jié)合性及種類
C語(yǔ)言運(yùn)算符號(hào)指的是運(yùn)算符號(hào)。C語(yǔ)言中的符號(hào)分為10類:算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位操作運(yùn)算符、賦值運(yùn)算符、條件運(yùn)算符、逗號(hào)運(yùn)算符、指針運(yùn)算符、求字節(jié)數(shù)運(yùn)算符和特殊運(yùn)算符2022-05-05
C語(yǔ)言動(dòng)態(tài)內(nèi)存函數(shù)詳解
這篇文章主要介紹了C語(yǔ)言動(dòng)態(tài)內(nèi)存函數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-09-09
解析C++的線性表鏈?zhǔn)酱鎯?chǔ)設(shè)計(jì)與相關(guān)的API實(shí)現(xiàn)
這篇文章主要介紹了解析C++中的線性表鏈?zhǔn)酱鎯?chǔ)設(shè)計(jì)與相關(guān)的API實(shí)現(xiàn),文中的實(shí)例很好地體現(xiàn)了如何創(chuàng)建和遍歷鏈表等基本操作,需要的朋友可以參考下2016-03-03
C++實(shí)現(xiàn)leetcode(3.最長(zhǎng)無(wú)重復(fù)字符的子串)
這篇文章主要介紹了C++實(shí)現(xiàn)leetcode(3.最長(zhǎng)無(wú)重復(fù)字符的子串),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07

