c++實現(xiàn)解析zip文件的示例代碼
更新時間:2023年12月08日 14:00:30 作者:spirits_of_snail
這篇文章主要為大家詳細介紹了如何利用c++實現(xiàn)解析zip文件,并對流式文件pptx內(nèi)容的修改,文中的示例代碼講解詳細,有需要的小伙伴可以參考一下
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 << "無法創(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)建源對象,并將其添加到 ZIP 存檔中 //zip_source_buffer內(nèi)部會自動釋放itemData內(nèi)存 zip_source* source = zip_source_buffer(archive, itemData, bufferSize, 0); if (source == NULL) { std::cout << "無法寫入 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 << "無法寫入 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)建多級文件夾 void createFolders(std::string rootPath); //獲取多級文件夾下所以文件列表 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)建對應(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; //獲取的是絕對路徑 getDirAllFilePath(inputDirPath, files); std::string rootPath(inputDirPath); for (size_t i = 0; i < files.size(); i++) { std::string::size_type rootSize = rootPath.length(); //獲取指定目錄下的相對路徑,作為zip包的條目名稱 std::string itemName = files[i].substr(rootSize + 1); std::cout << "entry: " << files[i].c_str() << std::endl; //通過文件創(chuàng)建zip_source源對象 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)建多級文件夾 //如果是文件,則創(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 }; // 向目錄加通配符,用于搜索第一個文件 strcpy(dirNew, folderPath); strcat(dirNew, "\\*.*"); hFind = FindFirstFile(dirNew, &findData); if (hFind == INVALID_HANDLE_VALUE) { std::cerr << "無法打開目錄:" << 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è)置為搜索到的目錄,并進行下一輪搜索 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 << "無法打開目錄:" << 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 << "無法獲取文件屬性:" << 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++實現(xiàn)解析zip文件的示例代碼的文章就介紹到這了,更多相關(guān)c++解析zip文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VSCode配置C/C++并添加非工作區(qū)頭文件的方法
這篇文章主要介紹了VSCode配置C/C++并添加非工作區(qū)頭文件的方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03Visual?C++?6.0添加一個對話框的實現(xiàn)步驟
VC6.0是微軟公司推出的一款集成開發(fā)環(huán)境,本文主要介紹了Visual?C++?6.0添加一個對話框的實現(xiàn)步驟,具有一定的參考價值,感興趣的可以了解一下2024-06-06C++知識點之inline函數(shù)、回調(diào)函數(shù)和普通函數(shù)
這篇文章主要給大家介紹了關(guān)于C++知識點之inline函數(shù)、回調(diào)函數(shù)和普通函數(shù)的相關(guān)使用方法,以及回調(diào)函數(shù)和普通函數(shù)的區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2021-07-07C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解
這篇文章主要介紹了C++命名空間?缺省參數(shù)?const總結(jié)?引用總結(jié)?內(nèi)聯(lián)函數(shù)?auto關(guān)鍵字詳解的相關(guān)資料,需要的朋友可以參考下2023-01-01