c++ 解析zip文件,實現對流式文件pptx內容的修改

libzip

  • 官網地址:
  • 示例代碼
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <zip.h>//解析原始zip內容,保存為新的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;}// 獲取條目數量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;}//保存為目標zip文件zip_t* archive = zip_open(outputPath, ZIP_CREATE | ZIP_TRUNCATE, nullptr);if (archive == nullptr) {std::cout << "無法創建 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;// 讀取內存空間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;}// 創建源對象,并將其添加到 ZIP 存檔中//zip_source_buffer內部會自動釋放itemData內存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);}}// 關閉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 //創建多級文件夾
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文件中的文件數量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;// 解壓文件到磁盤指定位置, 執行解壓之前, 需創建對應的文件夾,否則,解壓失敗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);}// 關閉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;//通過文件創建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 fileif (zip_file_add(archive, itemName .c_str(), source, ZIP_FL_OVERWRITE) < 0) {zip_source_free(source);zip_close(archive);return 2;}}// 關閉ZIP文件if (zip_close(archive) != 0) {std::cerr << "Failed to close archive" << std::endl;return -1;}return 0;
}//創建文件夾
int create_dir(const char *dir)
{
#ifdef WIN32if ((_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;}}
#elseif ((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;}}
#endifreturn 0;
}
//遞歸創建文件夾
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 ;
}//創建多級文件夾
//如果是文件,則創建文件所占目錄文件夾
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  WIN32HANDLE 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設置為搜索到的目錄,并進行下一輪搜索 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);
#elseDIR* 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)){// 如果是子目錄,則遞歸調用該函數獲取子文件夾中的文件路徑getFiles(entryPath.c_str(), filePaths);}else if (S_ISREG(entryStat.st_mode)){// 如果是文件,則添加到路徑列表中filePaths.push_back(entryPath);}}closedir(dir);
#endif
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207222.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207222.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207222.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue pc官網頂部導航欄組件

官網頂部導航分為一級導航和二級導航 導航的樣子 文件的層級 router 文件層級 header 組件代碼 <h1 class"logo-wrap"><router-link to"/"><img class"logo" :src"$config.company.logo" alt"" /><i…

直面雙碳目標,優維科技攜手奧意建筑打造綠色低碳建筑數智云平臺

優維“雙碳”戰略合作建筑 為落實創新驅動發展戰略&#xff0c;增強深圳工程建設領域科技創新能力&#xff0c;促進技術進步、科技成果轉化和推廣應用&#xff0c;根據《深圳市工程建設領域科技計劃項目管理辦法》《深圳市住房和建設局關于組織申報2022年深圳市工程建設領域科…

K8S集群優化的可執行優化

目錄 前期環境優化 1.永久關閉交換分區 2.#加載 ip_vs 模塊 3.調整內核參數 4.#使用Systemd管理的Cgroup來進行資源控制與管理 5.開機自啟kubelet 6.內核參數優化方案 7.etcd優化 默認etcd空間配額大小為 2G&#xff0c;超過 2G 將不再寫入數據。通過給etcd配置 --quo…

IO流(Java)

IO流 在學習IO流之前&#xff0c;我們首先了解一下File File File即文件或文件夾路徑對象&#xff0c;其示例類可以是存在路徑也可以是未創造路徑 File有什么用 用于創建或操作文件或文件夾 File常用API API部分看得懂會查會用即可 IO流 IO(Input 讀數據 Output寫數據…

Qt/QML編程學習之心得:工程中的文件(十二)

Qt生成了工程之后,尤其在QtCreator產生對應的project項目之后,就如同VisualStudio一樣,會產生相關的工程文件,那么這些工程文件都是做什么的呢?這里介紹一下。比如產生了一個Qt Widget application,當然如果Qt Quick Application工程會有所不同。 一、.pro和.pro.user …

企業計算機服務器中了360勒索病毒如何解密,勒索病毒解密數據恢復

網絡技術的不斷應用與發展&#xff0c;為企業的生產運營提供了極大便利&#xff0c;但隨之而來的網絡安全威脅也不斷增加。近期&#xff0c;云天數據恢復中心接到很多企業的求助&#xff0c;企業的計算機服務器遭到了360后綴勒索病毒攻擊&#xff0c;導致企業的所有數據被加密&…

游戲策劃常用的ChatGPT通用提示詞模板

游戲設計&#xff1a;請幫助我設計一個有趣的游戲。 游戲玩法&#xff1a;如何設計游戲的玩法&#xff1f; 游戲機制&#xff1a;如何設計游戲的機制&#xff1f; 游戲平衡&#xff1a;如何平衡游戲中的各種元素&#xff1f; 游戲美術&#xff1a;如何設計游戲的美術風格&a…

『PyTorch學習筆記』如何快速下載huggingface模型/數據—全方法總結

如何快速下載huggingface模型/數據—全方法總結 文章目錄 一. 如何快速下載huggingface大模型1.1. IDM(Windows)下載安裝連接1.2. 推薦 huggingface 鏡像站1.3. 管理huggingface_hub cache-system(緩存系統) 二. 參考文獻 一. 如何快速下載huggingface大模型 推薦 huggingface…

希亦洗地機跟追覓洗地機入手哪個更好?追覓跟希亦洗地機深度評估

近年來&#xff0c;洗地機可以同時處理干濕垃圾&#xff0c;同時降低用戶在清潔過程中的勞動強度&#xff0c;成為了家居清潔的新寵&#xff0c;但是目前市場上的品牌和型號層出不窮。用戶往往很難挑選&#xff0c;本文挑選了兩款目前口碑最好的兩款洗地機給大家做一個全面的評…

Android 記錄一些Framework開發的命令

源碼編譯流程 1. "source build/envsetup.sh" (source可以用 . 代替&#xff0c;即". build/envsetup.sh") 2. "lunch"&#xff0c;并選擇要編譯的項目或者"choosecombo" 3. "make idegen -j4" (這里的 -j4 表示用4線程來…

LeeCode每日刷題12.8

搜索插入位置 給定一個排序數組和一個目標值&#xff0c;在數組中找到目標值&#xff0c;并返回其索引。如果目標值不存在于數組中&#xff0c;返回它將會被按順序插入的位置。 請必須使用時間復雜度為 O(log n) 的算法。 示例 1: 輸入: nums [1,3,5,6], target 5 輸出: …

外貿行業的CRM系統和其它CRM有什么區別?

外貿行業對客戶管理的追求日益提高&#xff0c;為了應對客戶需求的變化和多元性&#xff0c;外貿企業需要借助CRM管理系統實現智能管理。下面&#xff0c;我們將詳細探討外貿CRM的概念、特點和具體應用。 什么是外貿CRM&#xff1f; 外貿CRM是指針對外貿行業的客戶關系管理系…

Nginx+Promtail+Loki+Grafana 升級ELK強大工具

最近客戶有個新需求,就是想查看網站的訪問情況,由于網站沒有做google的統計和百度的統計,所以訪問情況,只能通過日志查看,通過腳本的形式給客戶導出也不太實際,給客戶寫個簡單的頁面,咱也做不到 成熟的日志解決方案,那就是ELK,還有現在比較火的Loki,(當然還有很多其…

兩電腦共享鼠標鍵盤方案

一開始使用的是shareMouse 但是需要注冊還有很多不穩定問題 后來想買個雙拷線&#xff0c;又太貴&#xff0c;感覺不值的。 再后來&#xff0c;發現微軟有自己的系統上的 共享方案 &#xff0c;叫做 Mouse without Borders ,而且是免費的&#xff0c;只能在window電腦上使用…

Linus:我休假的時候也會帶著電腦,否則會感覺很無聊

目錄 Linux 內核最新版本動態 關于成為內核維護者 代碼好寫&#xff0c;人際關系難處理 內核維護者老齡化 內核中 Rust 的使用 關于 AI 的看法 參考 12.5-12.6 日&#xff0c;Linux 基金會組織的開源峰會&#xff08;OSS&#xff0c;Open Source Summit&#xff09;在日…

基于Java酒店管理系統

基于Java酒店管理系統 功能需求 1、客房管理&#xff1a;系統需要提供客房的信息管理功能&#xff0c;包括客房的類型、數量、價格、狀態&#xff08;如空閑、已預訂、已入住等&#xff09;等信息。此外&#xff0c;系統還應支持對客房信息的修改和查詢操作。 2、預訂管理&a…

日常開發日志

目錄 1、idea開發服務啟動的網頁地址不顯示前端樣式&#xff1a; 2、java Date 與myibits 的空判斷&#xff1a; 1、idea開發服務啟動的網頁地址不顯示前端樣式&#xff1a; idea開發時&#xff0c;tomcat啟動的后端彈出的網頁地址&#xff0c;呈現的網頁沒有樣式&#xff0…

報名學歷的同學,月底前記得申請抵扣個稅!

2024年度專項附加扣除開始確認啦&#xff01; 已經報名學歷&#xff08;自考、成考、開放大學&#xff09;的同學&#xff0c;記得去申請抵扣個稅哦&#xff01; 每個月的應納稅額可以減免400元呢&#xff0c;學歷提升在讀這幾年算下來&#xff0c;可以省不少錢。 注意&#x…

輪播插件Slick.js使用方法詳解

相比于Swiper而選擇使用Slick.js的原因主要是因為其兼容不錯并且在手機端的滑動效果更順暢 參數&#xff1a; 1.基本使用&#xff1a;一般使用只需前十個屬性 $(.box ul).slick({autoplay: true, //是否自動播放pauseOnHover: false, //鼠標懸停暫停自動播放speed: 1500, //…

linux鏈表應用2

以下是根據您的要求對示例代碼進行優化的結果&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h>// 定義路徑節點結構體 typedef struct PathNode {unsigned int fildid;char folderName[100]; // 文件夾名字struct PathNode* next…