Работа с ZIP-архивами в C++: libzip и zlib
В современной разработке на C++ часто возникает необходимость упаковывать и распаковывать данные. ZIP-архивы остаются одним из самых популярных форматов благодаря своей универсальности и поддержке сжатия. В этой статье мы рассмотрим две ключевые библиотеки для работы с ZIP в C++: libzip (высокоуровневая работа с архивами) и zlib (низкоуровневое сжатие). Вы узнаете, как установить библиотеки, создать архив, извлечь файлы и прочитать содержимое без распаковки.
Основные библиотеки для работы с ZIP в C++
- libzip — кроссплатформенная библиотека для создания, чтения и модификации ZIP-архивов. Поддерживает шифрование, потоки и работу с памятью.
- zlib — низкоуровневая библиотека сжатия данных (алгоритм Deflate). Используется как основа для libzip и других архиваторов.
- minizip — легковесная обёртка над zlib для работы с ZIP-форматом (часто входит в состав zlib).
Для большинства задач рекомендуется использовать libzip, так как она предоставляет более удобный и безопасный API.
Установка библиотек
В Linux (Ubuntu/Debian) установка выполняется через пакетный менеджер:
sudo apt-get install libzip-dev zlib1g-dev
Для macOS (Homebrew):
brew install libzip zlib
В Windows можно использовать vcpkg или скачать собранные бинарные файлы с официальных сайтов.
Подключение в CMakeLists.txt:
find_package(ZLIB REQUIRED)
find_package(LibZip REQUIRED)
target_link_libraries(your_project ZLIB::ZLIB libzip::zip)
Пример 1: Создание ZIP-архива с помощью libzip
Создадим архив example.zip и добавим в него текстовый файл:
#include <zip.h>
#include <iostream>
#include <string>
int main() {
const char* archive_name = "example.zip";
int err = 0;
// Открываем архив для записи
zip_t* archive = zip_open(archive_name, ZIP_CREATE | ZIP_TRUNCATE, &err);
if (!archive) {
std::cerr << "Ошибка создания архива: " << err << std::endl;
return 1;
}
// Данные для записи
const char* filename = "hello.txt";
const char* content = "Привет, мир! Hello, C++!";
// Создаём источник данных из памяти
zip_source_t* source = zip_source_buffer(archive, content, strlen(content), 0);
if (!source) {
std::cerr << "Ошибка создания источника" << std::endl;
zip_close(archive);
return 1;
}
// Добавляем файл в архив
zip_int64_t index = zip_file_add(archive, filename, source, ZIP_FL_OVERWRITE);
if (index < 0) {
std::cerr << "Ошибка добавления файла: " << zip_strerror(archive) << std::endl;
zip_source_free(source);
zip_close(archive);
return 1;
}
// Закрываем архив
zip_close(archive);
std::cout << "Архив создан: " << archive_name << std::endl;
return 0;
}
Пример 2: Распаковка ZIP-архива
Извлечём все файлы из архива в текущую директорию:
#include <zip.h>
#include <iostream>
#include <fstream>
int main() {
const char* archive_name = "example.zip";
int err = 0;
// Открываем архив для чтения
zip_t* archive = zip_open(archive_name, 0, &err);
if (!archive) {
std::cerr << "Ошибка открытия архива: " << 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) {
// Получаем имя файла
const char* filename = zip_get_name(archive, i, 0);
if (!filename) continue;
// Открываем файл внутри архива
zip_file_t* zf = zip_fopen_index(archive, i, 0);
if (!zf) {
std::cerr << "Не удалось открыть файл: " << filename << std::endl;
continue;
}
// Читаем и записываем данные
std::