📜  7zip - C 编程语言(1)

📅  最后修改于: 2023-12-03 14:38:53.662000             🧑  作者: Mango

7zip - C 编程语言介绍

7zip 是一款常用的开源压缩/解压软件,支持多种压缩格式。在 C 编程语言中,我们可以使用 7zip SDK 来集成 7zip 功能到我们的程序中。

7zip SDK 简介

7zip SDK 是 7zip 的开发包,它提供了 C++ 和 C# API,可以用于开发 Windows 应用程序,支持以下压缩格式:7z、ZIP、RAR、CAB、ARJ、GZIP、BZIP2、TAR、Z、XZ 和 ISO。

7zip SDK 支持多线程、AES256 加密和加密头处理,同时也提供了文件和文件夹的加密。

7zip SDK 安装和配置

你可以在 7zip 官方网站下载 7zip SDK 的最新版本,当前版本为 21.02 alpha。下载地址为:https://www.7-zip.org/sdk.html

下载后,按照提示进行安装即可。安装完成后,需要配置环境变量:

SET PATH="C:\Program Files\7-Zip\CPP\7zip";%PATH%

这个路径需要根据你的实际安装路径进行修改。

压缩文件

在 C 编程语言中使用 7zip SDK 压缩文件非常简单,只需要使用以下代码即可:

#include "7z.h"
#include "7zAlloc.h"
#include "7zBuf.h"
#include "7zCrc.h"
#include "7zFile.h"
#include "7zVersion.h"

...

void CompressFile(const char* archiveName, const char* fileName)
{
    CFileInStream archiveStream;
    CLookToRead lookStream;
    CSzDir dir;
    ISzAlloc allocImp;
    ISzAlloc tempImp;

    SZ_RESULT res;
    CArchiveDatabaseEx db;
    CObjectVector<CSzFileItem> *listFiles = &db.Items;

    SetLargePageMode();

    FileInStream_CreateVTable(&archiveStream);
    LookToRead_CreateVTable(&lookStream, False);
    lookStream.realStream = &archiveStream.s;
    LookToRead_Init(&lookStream);

    FileInStream_Open(&archiveStream.s, archiveName);

    SzArEx_Init(&db);
    res = SzArEx_Open(&db, &lookStream.s, &allocImp, &tempImp);

    SzDir_Init(&dir, &allocImp);

    dir.ArchiveDatabase = &db.db;
    dir.StartPos = db.DataStartPosition;
    dir.FileIndex = 0;

    SzDir_Load(&dir);

    printf("\nCompressing %s\n", fileName);
    res = SzCompress(p, source, srcLen, &outStream.s, &outBuf.s, props,
                     &propsSize, 0,
                     &g_Alloc, &g_Alloc);

    File_Close(&srcFile);
}

以上代码假设你已经包含了相应的头文件,并且设置了压缩和解压用到的变量。

解压文件

解压文件同样非常简单,只需要使用以下代码即可:

void ExtractArchive(const char* archiveName, const char* destDir)
{
    CFileInStream archiveStream;
    CLookToRead lookStream;
    CSzDir dir;
    ISzAlloc allocImp;
    ISzAlloc tempImp;
    UInt16* temp = NULL;

    SZ_RESULT res;
    CArchiveDatabaseEx db;
    CObjectVector<CSzFileItem> *listFiles = &db.Items;

    SetLargePageMode();

    FileInStream_CreateVTable(&archiveStream);
    LookToRead_CreateVTable(&lookStream, False);
    lookStream.realStream = &archiveStream.s;
    LookToRead_Init(&lookStream);

    FileInStream_Open(&archiveStream.s, archiveName);

    SzArEx_Init(&db);
    res = SzArEx_Open(&db, &lookStream.s, &allocImp, &tempImp);

    SzDir_Init(&dir, &allocImp);

    dir.ArchiveDatabase = &db.db;
    dir.StartPos = db.DataStartPosition;
    dir.FileIndex = SzArEx_GetNumFiles(&db) - 1;

    temp = (UInt16*)SzArEx_GetFileNameUtf16(&db, dir.FileIndex);
    size_t tempSize = (SzArEx_GetFileNameLen(&db, dir.FileIndex) + 1) * sizeof(temp[0]) / 2;
    printf("\nExtracting %ls\n", temp);
    SzDir_Load(&dir);

    ISzAlloc outAlloc = {SzAlloc, SzFree};

    UInt32 i;

    for (i = 0; i < db.Files.Size; i++)
    {
        size_t offset = 0;
        size_t destLen = 0;
        char* outBuffer = NULL;
        UInt32 outSizeProcessed = 0;

        const CSzFileItem* f = &(listFiles->Front()) + i;

        const UInt16* name = (const UInt16*)SzArEx_GetFileNameUtf16(&db, i);
        size_t nameLen = SzArEx_GetFileNameLen(&db, i);

        if (f->IsDir)
        {
            printf("\nExtracting %ls\n", name);
            continue;
        }

        offset += f->Size - f->PackSize;
        destLen = (size_t)f->Size;

        if (SzArEx_Extract(&db, &lookStream.s, i, &res, &outAlloc, &offset, destLen) != SZ_OK)
        {
            printf("error in SzArEx_Extract %d\n", res);
            continue;
        }

        outBuffer = (char*)outAlloc.alloc(outAlloc.p, (size_t)f->Size);
        ISzAlloc bufAlloc = {SzAlloc, SzFree};
        size_t bufferProcessed = 0;

        while (outSizeProcessed < f->Size)
        {
            size_t curSize = bufferProcessed + (f->Size - outSizeProcessed);

            if (curSize > INT_MAX)
            {
                curSize = INT_MAX;
            }

            res = FileOutStream_Read(&fileStream.s, outBuffer + outSizeProcessed, curSize, &outSizeProcessed);
            if (res != SZ_OK)
            {
                printf("error in FileOutStream_Read %d\n", res);
                break;
            }
        }

        if (outSizeProcessed != f->Size)
        {
            printf("error in reading extracted file %ls\n", name);
            return;
        }

        File_Close(&fileStream.s);
    }
}

以上代码同样假设你已经包含了相应的头文件,并且设置了解压用到的变量。

技术总结

本文简单介绍了使用 7zip SDK 在 C 编程语言中对压缩/解压功能进行集成。如果你需要更详细的信息,可以参考 7zip SDK 的官方文档。

有时候在 Windows 上使用 7zip 是非常方便的,不过如果你的程序需要跨平台,建议使用 libarchive 或者 libzip 等开源库,它们支持多种操作系统和多种压缩格式。