将7z解压功能以lib的方式集成到工程中

一、官网链接

首页
http://www.7-zip.org/
下载地址
http://www.7-zip.org/download.html
选择 7-Zip Source code一栏的 Download,
我下载的是 7z1602-src.7z

二、相关说明

将下载的包解压,进入7z1602-src\C\Util\7z目录,会看见一个7z.dsw的vc6的工程项目,用自己当前vs版本打开,直接升级即可。
这个工程会生成一个7zDec.exe的可执行程序,它提供了只针对7z格式文件简单的解压缩功能(正好满足我的需求),解压算法采用的是LZMA。
LZMA是7z程序对7z格式文件默认的压缩算法,LZMA提供了高压缩率和非常快的解压速度。
注意事项:可能对中文路径支持有问题,且不支持加密文件等其它高级特性

三、代码修改

打开工程后,先将项目的类型改为lib,在7z1602-src\C\Util\7z\7zMain.c文件中新增extract_7z函数

/*
    pSrcFile : .7z文件名(可包含路径)
    pDstPath : 解压至目标文件夹(必须用绝对路径,目录必须存在,如果为空,直接解压到当前目录)
*/
int MY_CDECL extract_7z(char* pSrcFile, wchar_t* pDstPath) {
    int useDestPath = 0;
    if (pSrcFile == NULL)
    {
        return -1;
    }
    if (pDstPath)
    {
        useDestPath = 1;
        wchar_t szDstPath[MAX_PATH] = { 0 };
        wcscpy(szDstPath, pDstPath);
        pDstPath = szDstPath;
        PathAddBackslash(szDstPath);
        if (!PathFileExists(pDstPath))
        {
            return -1;
        }
    }
    CFileInStream archiveStream;
    CLookToRead lookStream;
    CSzArEx db;
    SRes res;
    ISzAlloc allocImp;
    ISzAlloc allocTempImp;
    UInt16 *temp = NULL;
    UInt16 *destPath = NULL;
    size_t tempSize = 0;
    size_t destSize = 0;
    // UInt32 parents[NUM_PARENTS_MAX];

    printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");

#if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE)
    g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
#endif

    allocImp.Alloc = SzAlloc;
    allocImp.Free = SzFree;

    allocTempImp.Alloc = SzAllocTemp;
    allocTempImp.Free = SzFreeTemp;

#ifdef UNDER_CE
    if (InFile_OpenW(&archiveStream.file, L"\test.7z"))
#else
    if (InFile_Open(&archiveStream.file, pSrcFile))
#endif
    {
        PrintError("can not open input file");
        return 1;
    }

    FileInStream_CreateVTable(&archiveStream);
    LookToRead_CreateVTable(&lookStream, False);

    lookStream.realStream = &archiveStream.s;
    LookToRead_Init(&lookStream);

    CrcGenerateTable();

    SzArEx_Init(&db);

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

    if (res == SZ_OK)
    {
        int listCommand = 0, testCommand = 0, fullPaths = 1;

        if (res == SZ_OK)
        {
            UInt32 i;

            /*
            if you need cache, use these 3 variables.
            if you use external function, you can make these variable as static.
            */
            UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
            Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
            size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

            for (i = 0; i < db.NumFiles; i++)
            {
                size_t offset = 0;
                size_t outSizeProcessed = 0;
                // const CSzFileItem *f = db.Files + i;
                size_t len;
                unsigned isDir = SzArEx_IsDir(&db, i);
                if (listCommand == 0 && isDir && !fullPaths)
                    continue;
                len = SzArEx_GetFileNameUtf16(&db, i, NULL);
                // len = SzArEx_GetFullNameLen(&db, i);

                if (len > tempSize)
                {
                    SzFree(NULL, temp);
                    tempSize = len;
                    temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));
                    if (!temp)
                    {
                        res = SZ_ERROR_MEM;
                        break;
                    }
                }

                SzArEx_GetFileNameUtf16(&db, i, temp);
                /*
                if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp)
                {
                res = SZ_ERROR_FAIL;
                break;
                }
                */

                if (listCommand)
                {
                    char attr[8], s[32], t[32];
                    UInt64 fileSize;

                    GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);

                    fileSize = SzArEx_GetFileSize(&db, i);
                    UInt64ToStr(fileSize, s);

                    if (SzBitWithVals_Check(&db.MTime, i))
                        ConvertFileTimeToString(&db.MTime.Vals[i], t);
                    else
                    {
                        size_t j;
                        for (j = 0; j < 19; j++)
                            t[j] = ' ';
                        t[j] = '\0';
                    }

                    printf("%s %s %10s  ", t, attr, s);
                    res = PrintString(temp);
                    if (res != SZ_OK)
                        break;
                    if (isDir)
                        printf("/");
                    printf("\n");
                    continue;
                }

                fputs(testCommand ?
                    "Testing    " :
                    "Extracting ",
                    stdout);
                res = PrintString(temp);
                if (res != SZ_OK)
                    break;

                if (isDir)
                    printf("/");
                else
                {
                    res = SzArEx_Extract(&db, &lookStream.s, i,
                        &blockIndex, &outBuffer, &outBufferSize,
                        &offset, &outSizeProcessed,
                        &allocImp, &allocTempImp);
                    if (res != SZ_OK)
                        break;
                }

                if (!testCommand)
                {
                    CSzFile outFile;
                    size_t processedSize;
                    size_t j;
                    UInt16 *name = (UInt16 *)temp;
                    if (useDestPath) {
                        SzFree(NULL, destPath);
                        destSize = wcslen(pDstPath);
                        destSize += tempSize;
                        destPath = (UInt16 *)SzAlloc(NULL, destSize* sizeof(destPath[0]));
                        if (!destPath)
                        {
                            res = SZ_ERROR_MEM;
                            break;
                        }
                        wcscpy(destPath, pDstPath);
                        wcscat(destPath, temp);
                        name = destPath + wcslen(pDstPath);
                    }
                    else
                        destPath = (UInt16 *)name;


                    for (j = 0; name[j] != 0; j++)
                    if (name[j] == '/')
                    {
                        if (fullPaths)
                        {
                            name[j] = 0;
                            MyCreateDir(destPath);
                            name[j] = CHAR_PATH_SEPARATOR;
                        }
                        else
                            destPath = name + j + 1;
                    }

                    if (isDir)
                    {
                        MyCreateDir(destPath);
                        printf("\n");
                        continue;
                    }
                    else if (OutFile_OpenUtf16(&outFile, destPath))
                    {
                        PrintError("can not open output file");
                        res = SZ_ERROR_FAIL;
                        break;
                    }

                    processedSize = outSizeProcessed;

                    if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
                    {
                        PrintError("can not write output file");
                        res = SZ_ERROR_FAIL;
                        break;
                    }

                    if (File_Close(&outFile))
                    {
                        PrintError("can not close output file");
                        res = SZ_ERROR_FAIL;
                        break;
                    }

#ifdef USE_WINDOWS_FILE
                    if (SzBitWithVals_Check(&db.Attribs, i))
                        SetFileAttributesW(destPath, db.Attribs.Vals[i]);
#endif              
                }
                printf("\n");
            }
            IAlloc_Free(&allocImp, outBuffer);
        }
    }

    SzArEx_Free(&db, &allocImp);
    SzFree(NULL, temp);
    if (useDestPath) {
        SzFree(NULL, destPath);
    }

    File_Close(&archiveStream.file);

    if (res == SZ_OK)
    {
        printf("\nEverything is Ok\n");
        return 0;
    }

    if (res == SZ_ERROR_UNSUPPORTED)
        PrintError("decoder doesn't support this archive");
    else if (res == SZ_ERROR_MEM)
        PrintError("can not allocate memory");
    else if (res == SZ_ERROR_CRC)
        PrintError("CRC error");
    else
        printf("\nERROR #%d\n", res);

    return 1;
}

在引用此lib的工程中调用此函数即可

extern "C" int __cdecl extract_7z(char* pSrcFile, wchar_t* pDstPath);
void Extract7z() {
    extract_7z("test.7z", L"D:\\1234");
}

四、参考链接

https://blog.byneil.com/category/zip-7z/7zip/
http://www.cnblogs.com/davad/p/3578628.html

你可能感兴趣的:(7z)