Linux c 在内存中创建zip,最后写入测试

一、libzip 和 zlib 的关

  1. zlib 是一个底层的数据压缩库,它实现了 DEFLATE 压缩算法。它本身不处理 ZIP 文件格式。
  2. libzip 是一个用于创建和操作 ZIP 归档文件的库。ZIP 文件格式内部使用 DEFLATE 算法进行压缩。
  3. libzip 依赖于 zlib 来执行实际的压缩工作。当你用 libzip 添加一个文件时,它会自动调用 zlib 来压缩数据,然后将压缩后的数据写入 ZIP 归档的正确位置。

二、使用libzip 在压缩内存中的数据,同时zip 压缩文件也保存在内存中

复制代码
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <sstream>

#include <zip.h>
static int use_data(void *pbtZipData, size_t nZipData, const char *pstrFileName)
{
    /* example implementation that writes pbtZipData to file */
    FILE *fp;

    if (pbtZipData == NULL) {
        if (remove(pstrFileName) < 0 && errno != ENOENT) {
            fprintf(stderr, "can't remove %s: %s\n", pstrFileName, strerror(errno));
            return -1;
        }
        return 0;
    }

    if ((fp = fopen(pstrFileName, "wb")) == NULL) {
        fprintf(stderr, "can't open %s: %s\n", pstrFileName, strerror(errno));
        return -1;
    }
    if (fwrite(pbtZipData, 1, nZipData, fp) < nZipData) {
        fprintf(stderr, "can't write %s: %s\n", pstrFileName, strerror(errno));
        fclose(fp);
        return -1;
    }
    if (fclose(fp) < 0) {
        fprintf(stderr, "can't write %s: %s\n", pstrFileName, strerror(errno));
        return -1;
    }

    return 0;
}

bool AddFilesToZip(zip_t* pZipHandle, const char* pstrFileName, const char* pstrData)
{
    if(pZipHandle && pstrData && pstrFileName){
        zip_source_t* pstZipSource = zip_source_buffer(pZipHandle, pstrData, strlen(pstrData), 0);
        if (zip_file_add(pZipHandle, pstrFileName, pstZipSource, ZIP_FL_ENC_UTF_8) >= 0) {
            return true;
        }
        else{
            std::cerr << "nZipError adding source: " << zip_strerror(pZipHandle) << std::endl;
        }
    }
    
    return false;
}

int main()
{
    zip_error_t nZipError;
    zip_error_init(&nZipError);

    zip_source_t* pstZipSource = zip_source_buffer_create(NULL, 0, 1, &nZipError);
    if (pstZipSource == NULL) {
        std::cerr << "can't create source: " << zip_error_strerror(&nZipError) << std::endl;
        zip_error_fini(&nZipError);
        return 1;
    }

    zip_t* pZipHandle = zip_open_from_source(pstZipSource, ZIP_TRUNCATE, &nZipError);
    if ((pZipHandle ) == NULL) {
        std::cerr << "can't open zip from source: " << zip_error_strerror(&nZipError) << std::endl;
        zip_source_free(pstZipSource);
        zip_error_fini(&nZipError);
        return 1;
    }

    zip_error_fini(&nZipError);

    zip_source_keep(pstZipSource);

    if (!AddFilesToZip(pZipHandle, "123.log"/*测试, 压缩包内部文件*/, "tt"/*测试, 文件内容*/)){
        return 1;
    }

    if (zip_close(pZipHandle) < 0) {
        std::cerr << "can't close zip pstrFileName" << zip_strerror(pZipHandle) << std::endl;
        return 1;
    }


    //测试, 主要拿到zip 二进制数据,保存文件。参考 examples/in-memory.c
    unsigned char* pbtZipData = NULL;
    int nZipData = 0;
    if (!zip_source_is_deleted(pstZipSource)) {
        zip_stat_t zst;

        if (zip_source_stat(pstZipSource, &zst) < 0) {
            fprintf(stderr, "can't stat source: %s\n", zip_error_strerror(zip_source_error(pstZipSource)));
            return 1;
        }

        nZipData = zst.size;

        if (zip_source_open(pstZipSource) < 0) {
            fprintf(stderr, "can't open source: %s\n", zip_error_strerror(zip_source_error(pstZipSource)));
            return 1;
        }
        if ((pbtZipData = (unsigned char*)malloc(nZipData)) == NULL) {
            fprintf(stderr, "malloc failed: %s\n", strerror(errno));
            zip_source_close(pstZipSource);
            return 1;
        }
        if ((zip_uint64_t)zip_source_read(pstZipSource, pbtZipData, nZipData) < nZipData) {
            fprintf(stderr, "can't read pbtZipData from source: %s\n", zip_error_strerror(zip_source_error(pstZipSource)));
            zip_source_close(pstZipSource);
            free(pbtZipData);
            return 1;
        }
        zip_source_close(pstZipSource);
    }

    /* we're done with pstZipSource */
    zip_source_free(pstZipSource);

    /* use new pbtZipData */
    use_data(pbtZipData, nZipData, "123.zip"/*测试, 压缩包文件名*/);

    free(pbtZipData);
}
相关推荐
QYRdata29 分钟前
2026-2032年图形处理云服务器CAGR预计达18.7%
运维·服务器·服务发现
分布式存储与RustFS1 小时前
图床搬到自己的对象存储:PicGo 加 S3 插件的完整配置
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
GeW1 小时前
制造强国底座:Linux与数据库驱动的新型工业基础设施
linux
月落汀兰1 小时前
建池后类型不可修改!深度拆解 Ceph PG 放置组,副本 / 纠删码池选型,快照与命名空间避坑
运维·ceph
xiaoye-duck1 小时前
《Linux 网络编程》深入理解 IO 多路复用:select 函数详解与 Echo 服务实战
linux·网络
Tairitsu_H1 小时前
[Linux系统] 命令行参数 | 环境变量 | 程序地址空间
linux·环境变量·命令行参数·程序地址空间
雯宝2 小时前
devices_init / buses_init / classes_init / firmware_init / hypervisor_init 函数
linux
极光通讯2 小时前
呆滞库存回收定价逻辑:如何评估DDR4内存和SATA SSD的回收价值
服务器·ssd
技术人生0012 小时前
VMware Workstation 安装 Ubuntu 24.04 LTS 完整教程
运维·服务器·ubuntu
YumiProxy2 小时前
动态IP冲突排查实战:从ARP检测到DHCP地址池的完整链路
服务器·网络·网络协议·tcp/ip·ip