【问题标题】:Simple way to unzip a .zip file using zlib [duplicate]使用 zlib 解压缩 .zip 文件的简单方法 [重复]
【发布时间】:2012-05-13 11:36:24
【问题描述】:

是否有一个简单的示例说明如何解压缩 .zip 文件并将文件提取到目录中?我目前正在使用 zlib,虽然我知道 zlib 不直接处理 zip 文件,但 zlibs 的“contrib”库中似乎还有一些额外的东西。我注意到并阅读了“minizip”,在阅读了一些文档并查看了一些代码之后,我没有看到如何解压缩 .zip 文件并将文件解压缩到目录的简单示例。

我想找到一种独立于平台的方法,但如果这不可能,那么我需要为 windows 和 mac 找到一种方法。

【问题讨论】:

标签: c++ zip zlib unzip


【解决方案1】:

zlib 处理 deflate 压缩/解压缩算法,但在 ZIP 文件中还有更多内容。

你可以试试libzip。它免费、便携且易于使用。

更新:这里我附上了 libzip 的快速'n'dirty 示例,省略了所有错误控制:

#include <zip.h>

int main()
{
    //Open the ZIP archive
    int err = 0;
    zip *z = zip_open("foo.zip", 0, &err);

    //Search for the file of given name
    const char *name = "file.txt";
    struct zip_stat st;
    zip_stat_init(&st);
    zip_stat(z, name, 0, &st);

    //Alloc memory for its uncompressed contents
    char *contents = new char[st.size];

    //Read the compressed file
    zip_file *f = zip_fopen(z, name, 0);
    zip_fread(f, contents, st.size);
    zip_fclose(f);

    //And close the archive
    zip_close(z);

    //Do something with the contents
    //delete allocated memory
    delete[] contents;
}

【讨论】:

  • 您能否提供一个如何使用 libzip 解压缩文件的简单示例?
  • 没问题。查看更新的答案。
  • 经过几天与 libzip 搏斗以使其在 Windows 上编译后,结果发现您帖子中的代码无法编译。 zip_stat 是一个函数,而不是你提到的类型
  • @judeclarke - 实际上两者都是!在 C 中没有歧义,但在 C++ 中有。只需将zip_stat st; 更改为struct zip_stat st; 即可。
  • 当我尝试用 g++ o ubuntu 编译它时,它给出了“未定义的函数引用”
【解决方案2】:

Minizip 确实有一个示例程序来演示其用法 - 这些文件称为 minizip.c 和 miniunz.c。

更新:我有几分钟的时间,所以我为您快速制作了这个简单的示例。这是非常臭的C,如果没有重大改进,我不会使用它。希望这足以让您暂时继续前进。

// uzip.c - Simple example of using the minizip API.
// Do not use this code as is! It is educational only, and probably
// riddled with errors and leaks!
#include <stdio.h>
#include <string.h>

#include "unzip.h"

#define dir_delimter '/'
#define MAX_FILENAME 512
#define READ_SIZE 8192

int main( int argc, char **argv )
{
    if ( argc < 2 )
    {
        printf( "usage:\n%s {file to unzip}\n", argv[ 0 ] );
        return -1;
    }

    // Open the zip file
    unzFile *zipfile = unzOpen( argv[ 1 ] );
    if ( zipfile == NULL )
    {
        printf( "%s: not found\n" );
        return -1;
    }

    // Get info about the zip file
    unz_global_info global_info;
    if ( unzGetGlobalInfo( zipfile, &global_info ) != UNZ_OK )
    {
        printf( "could not read file global info\n" );
        unzClose( zipfile );
        return -1;
    }

    // Buffer to hold data read from the zip file.
    char read_buffer[ READ_SIZE ];

    // Loop to extract all files
    uLong i;
    for ( i = 0; i < global_info.number_entry; ++i )
    {
        // Get info about current file.
        unz_file_info file_info;
        char filename[ MAX_FILENAME ];
        if ( unzGetCurrentFileInfo(
            zipfile,
            &file_info,
            filename,
            MAX_FILENAME,
            NULL, 0, NULL, 0 ) != UNZ_OK )
        {
            printf( "could not read file info\n" );
            unzClose( zipfile );
            return -1;
        }

        // Check if this entry is a directory or file.
        const size_t filename_length = strlen( filename );
        if ( filename[ filename_length-1 ] == dir_delimter )
        {
            // Entry is a directory, so create it.
            printf( "dir:%s\n", filename );
            mkdir( filename );
        }
        else
        {
            // Entry is a file, so extract it.
            printf( "file:%s\n", filename );
            if ( unzOpenCurrentFile( zipfile ) != UNZ_OK )
            {
                printf( "could not open file\n" );
                unzClose( zipfile );
                return -1;
            }

            // Open a file to write out the data.
            FILE *out = fopen( filename, "wb" );
            if ( out == NULL )
            {
                printf( "could not open destination file\n" );
                unzCloseCurrentFile( zipfile );
                unzClose( zipfile );
                return -1;
            }

            int error = UNZ_OK;
            do    
            {
                error = unzReadCurrentFile( zipfile, read_buffer, READ_SIZE );
                if ( error < 0 )
                {
                    printf( "error %d\n", error );
                    unzCloseCurrentFile( zipfile );
                    unzClose( zipfile );
                    return -1;
                }

                // Write data to file.
                if ( error > 0 )
                {
                    fwrite( read_buffer, error, 1, out ); // You should check return of fwrite...
                }
            } while ( error > 0 );

            fclose( out );
        }

        unzCloseCurrentFile( zipfile );

        // Go the the next entry listed in the zip file.
        if ( ( i+1 ) < global_info.number_entry )
        {
            if ( unzGoToNextFile( zipfile ) != UNZ_OK )
            {
                printf( "cound not read next file\n" );
                unzClose( zipfile );
                return -1;
            }
        }
    }

    unzClose( zipfile );

    return 0;
}

我在 Windows 上使用 MinGW/MSYS 构建并测试了它,如下所示:

contrib/minizip/$ gcc -I../.. -o unzip uzip.c unzip.c ioapi.c ../../libz.a
contrib/minizip/$ ./unzip.exe /j/zlib-125.zip

【讨论】:

  • 我之前研究过那个例子,这是一个巨大的例子。你能提供一个更简单的例子吗?
  • @judeclarke,我今天离开我的开发箱,但我会尽可能发布更小/更简单的东西!
  • 您只需要花时间阅读头文件和示例。首先查看 zip.h 和 unzip.h 以了解提供的功能以及它们的作用。然后查看 minizip.c 和 miniunz.c 看看它们是如何使用的。
  • 使用 unzReadCurrentFile 是否不可能在 zip 中包含 2 个“打开”文件?
  • @paulm: 只需创建两个 unzFile 实例
猜你喜欢
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 2021-11-23
相关资源
最近更新 更多