c++ - Manera simple de descomprimir un archivo.zip usando zlib
unzip (2)
Esta pregunta ya tiene una respuesta aquí:
- Descomprime un archivo comprimido usando zlib 3 respuestas
¿Hay un ejemplo simple de cómo descomprimir un archivo .zip y extraer los archivos a un directorio? Actualmente estoy usando zlib, y si bien entiendo que zlib no trata directamente con archivos zip, parece que hay varias cosas adicionales en la biblioteca "contrib" de zlibs. Noté y leí sobre "minizip", y después de leer algunos documentos y mirar algunos de los códigos, no veo un ejemplo simple de cómo descomprimir un archivo .zip y extraer los archivos a un directorio.
Me gustaría encontrar una plataforma independiente para hacerlo, pero si eso no es posible, entonces necesito encontrar una forma de Windows y Mac.
Minizip tiene un ejemplo de programas para demostrar su uso: los archivos se llaman minizip.c y miniunz.c.
Actualización: Tenía unos minutos, así que inventé este ejemplo rápido y escueto para ti. Es muy maloliente C, y no lo usaría sin grandes mejoras. Espero que sea suficiente para que puedas continuar por el momento.
// 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;
}
Lo construí y probé con MinGW / MSYS en Windows de esta manera:
contrib/minizip/$ gcc -I../.. -o unzip uzip.c unzip.c ioapi.c ../../libz.a
contrib/minizip/$ ./unzip.exe /j/zlib-125.zip
zlib
maneja el algoritmo de compresión / descompresión de desinflado , pero hay más que eso en un archivo ZIP.
Puedes probar libzip . Es gratis, portátil y fácil de usar.
ACTUALIZACIÓN: Aquí adjunto quick''n''dirty ejemplo de libzip, con todos los controles de error ommited:
#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;
}