wake-up-neo.net

Einfache Möglichkeit, eine ZIP-Datei mit zlib zu entpacken

Gibt es ein einfaches Beispiel für das Entpacken einer ZIP-Datei und das Extrahieren der Dateien in ein Verzeichnis? Ich verwende derzeit zlib, und obwohl ich verstehe, dass zlib nicht direkt mit Zip-Dateien umgeht, scheint es in der "contrib" -Bibliothek von zlibs mehrere zusätzliche Dinge zu geben. Ich habe "Minizip" bemerkt und gelesen, und nachdem ich einige Dokumente gelesen und einen Teil des Codes angesehen habe, sehe ich kein einfaches Beispiel dafür, wie man eine ZIP-Datei entpackt und die Dateien in ein Verzeichnis extrahiert.

Ich würde gerne einen plattformunabhängigen Weg finden, aber wenn das nicht möglich ist, muss ich einen Weg für Windows und Mac finden.

38
judeclarke

zlib behandelt den Komprimierungs-/Dekomprimierungsalgorithmus deflate, aber es gibt mehr als das in einer Zip-Datei.

Sie können versuchen libzip . Es ist kostenlos, portabel und einfach zu bedienen.

UPDATE: Hier füge ich ein Beispiel für libzip bei, wobei alle Fehlersteuerelemente weggelassen wurden:

#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;
}
49
rodrigo

Minizip hat ein Beispielprogramm, um seine Verwendung zu demonstrieren - die Dateien heißen minizip.c und miniunz.c.

Update: Ich hatte ein paar Minuten Zeit, um dieses schnelle Beispiel für Sie zu erstellen. Es riecht sehr nach C und ich würde es nicht ohne größere Verbesserungen verwenden. Hoffentlich ist es genug, um dich für den Moment zum Laufen zu bringen.

// 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;
}

Ich habe es mit MinGW/MSYS unter Windows so gebaut und getestet:

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