Trabajo con archivos ZIP en C++: libzip y zlib
En el desarrollo moderno en C++, a menudo surge la necesidad de empaquetar y descomprimir datos. Los archivos ZIP siguen siendo uno de los formatos más populares debido a su versatilidad y soporte de compresión. En este artículo, analizaremos dos bibliotecas clave para trabajar con ZIP en C++: libzip (trabajo de alto nivel con archivos) y zlib (compresión de bajo nivel). Aprenderá cómo instalar las bibliotecas, crear un archivo, extraer archivos y leer el contenido sin descomprimir.
Bibliotecas principales para trabajar con ZIP en C++
- libzip — biblioteca multiplataforma para crear, leer y modificar archivos ZIP. Soporta cifrado, flujos y trabajo con memoria.
- zlib — biblioteca de compresión de datos de bajo nivel (algoritmo Deflate). Se utiliza como base para libzip y otros archivadores.
- minizip — envoltorio ligero sobre zlib para trabajar con el formato ZIP (a menudo incluido en zlib).
Para la mayoría de las tareas, se recomienda usar libzip, ya que proporciona una API más conveniente y segura.
Instalación de las bibliotecas
En Linux (Ubuntu/Debian), la instalación se realiza a través del gestor de paquetes:
sudo apt-get install libzip-dev zlib1g-devPara macOS (Homebrew):
brew install libzip zlibEn Windows, puede usar vcpkg o descargar los archivos binarios compilados desde los sitios oficiales.
Conexión en CMakeLists.txt:
find_package(ZLIB REQUIRED)find_package(LibZip REQUIRED)target_link_libraries(your_project ZLIB::ZLIB libzip::zip)Ejemplo 1: Creación de un archivo ZIP con libzip
Crearemos un archivo example.zip y agregaremos un archivo de texto:
#include <zip.h>#include <iostream>#include <string>
int main() { const char* archive_name = "example.zip"; int err = 0;
// Abrimos el archivo para escritura zip_t* archive = zip_open(archive_name, ZIP_CREATE | ZIP_TRUNCATE, &err); if (!archive) { std::cerr << "Error al crear el archivo: " << err << std::endl; return 1; }
// Datos para escribir const char* filename = "hello.txt"; const char* content = "¡Hola, mundo! Hello, C++!"; // Creamos una fuente de datos desde la memoria zip_source_t* source = zip_source_buffer(archive, content, strlen(content), 0); if (!source) { std::cerr << "Error al crear la fuente" << std::endl; zip_close(archive); return 1; }
// Agregamos el archivo al archivo ZIP zip_int64_t index = zip_file_add(archive, filename, source, ZIP_FL_OVERWRITE); if (index < 0) { std::cerr << "Error al agregar el archivo: " << zip_strerror(archive) << std::endl; zip_source_free(source); zip_close(archive); return 1; }
// Cerramos el archivo zip_close(archive); std::cout << "Archivo creado: " << archive_name << std::endl; return 0;}Ejemplo 2: Descompresión de un archivo ZIP
Extraeremos todos los archivos del archivo ZIP en el directorio actual:
#include <zip.h>#include <iostream>#include <fstream>
int main() { const char* archive_name = "example.zip"; int err = 0;
// Abrimos el archivo para lectura zip_t* archive = zip_open(archive_name, 0, &err); if (!archive) { std::cerr << "Error al abrir el archivo: " << err << std::endl; return 1; }
zip_int64_t num_entries = zip_get_num_entries(archive, 0); for (zip_int64_t i = 0; i < num_entries; ++i) { // Obtenemos el nombre del archivo const char* filename = zip_get_name(archive, i, 0); if (!filename) continue;
// Abrimos el archivo dentro del ZIP zip_file_t* file = zip_fopen_index(archive, i, 0); if (!file) continue;
// Leemos y escribimos el contenido char buffer[1024]; zip_int64_t bytes_read; std::ofstream outfile(filename, std::ios::binary); while ((bytes_read = zip_fread(file, buffer, sizeof(buffer))) > 0) { outfile.write(buffer, bytes_read); }
zip_fclose(file); outfile.close(); std::cout << "Extraído: " << filename << std::endl; }
zip_close(archive); std::cout << "Descompresión completada." << std::endl; return 0;}Ejemplo 3: Lectura del contenido sin descompresión
Podemos leer el contenido de un archivo dentro del ZIP sin extraerlo físicamente:
#include <zip.h>#include <iostream>
int main() { const char* archive_name = "example.zip"; int err = 0;
zip_t* archive = zip_open(archive_name, 0, &err); if (!archive) { std::cerr << "Error al abrir el archivo" << std::endl; return 1; }
// Buscamos un archivo específico por nombre const char* target = "hello.txt"; zip_int64_t index = zip_name_locate(archive, target, 0); if (index < 0) { std::cerr << "Archivo no encontrado: " << target << std::endl; zip_close(archive); return 1; }
// Abrimos el archivo y leemos su contenido zip_file_t* file = zip_fopen_index(archive, index, 0); if (!file) { std::cerr << "Error al abrir el archivo en el ZIP" << std::endl; zip_close(archive); return 1; }
char buffer[256]; zip_int64_t bytes_read; std::cout << "Contenido de " << target << ":" << std::endl; while ((bytes_read = zip_fread(file, buffer, sizeof(buffer) - 1)) > 0) { buffer[bytes_read] = '\0'; std::cout << buffer; } std::cout << std::endl;
zip_fclose(file); zip_close(archive); return 0;}Conclusión
Las bibliotecas libzip y zlib proporcionan herramientas potentes y flexibles para trabajar con archivos ZIP en C++. libzip simplifica las operaciones de alto nivel como la creación, extracción y modificación de archivos, mientras que zlib ofrece control de bajo nivel sobre la compresión de datos. Para la mayoría de los proyectos, se recomienda comenzar con libzip, ya que abstrae las complejidades del formato ZIP y proporciona una API más limpia y segura.
Para obtener más información, consulte la documentación oficial: