Работа с ZIP/архивами в C++: обзор библиотек и практические примеры
Архивация данных — одна из ключевых задач в разработке программного обеспечения. В C++ нет встроенной поддержки ZIP-формата, однако существует несколько зрелых и проверенных библиотек, которые позволяют легко упаковывать, распаковывать и модифицировать ZIP-архивы. В этой статье мы рассмотрим основные инструменты: zlib, minizip и libzip, а также приведём практические примеры кода.
1. Базовые концепции работы с ZIP в C++
ZIP — это формат сжатия без потерь, который поддерживает несколько алгоритмов (Deflate, BZip2, LZMA). Для работы с ним в C++ обычно используются три подхода:
- Прямая работа с zlib — низкоуровневое сжатие/разжатие потоков данных, но без поддержки структуры ZIP-файла.
- minizip — надстройка над zlib, предоставляющая функции для создания и чтения ZIP-архивов.
- libzip — полнофункциональная библиотека с поддержкой редактирования, удаления и добавления файлов в существующие архивы.
2. Библиотека zlib
zlib — это фундаментальная библиотека сжатия, на которой построены многие ZIP-решения. Она предоставляет функции compress() и uncompress() для работы с сырыми данными.
Пример: сжатие строки с помощью zlib
#include <iostream>
#include <string>
#include <zlib.h>
int main() {
std::string input = "Пример текста для сжатия в C++!";
uLong srcLen = input.size();
uLong destLen = compressBound(srcLen);
char* compressed = new char[destLen];
if (compress((Bytef*)compressed, &destLen,
(const Bytef*)input.data(), srcLen) == Z_OK) {
std::cout << "Сжато: " << srcLen << " -> " << destLen << " байт\n";
}
delete[] compressed;
return 0;
}
Примечание: Для работы с zlib необходимо подключить заголовочный файл zlib.h и линковаться с библиотекой -lz.
3. Библиотека minizip
minizip — это легковесная обёртка над zlib, которая позволяет создавать и извлекать ZIP-архивы. Она распространяется в составе исходников zlib (папка contrib/minizip).
Пример: создание ZIP-архива с одним файлом
#include <iostream>
#include <zip.h> // minizip
int main() {
zipFile zf = zipOpen("example.zip", APPEND_STATUS_CREATE);
if (!zf) {
std::cerr << "Ошибка создания архива\n";
return 1;
}
zip_fileinfo info = {0};
const char* filename = "test.txt";
const char* content = "Hello from minizip!";
if (zipOpenNewFileInZip(zf, filename, &info,
nullptr, 0, nullptr, 0,
nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION) == ZIP_OK) {
zipWriteInFileInZip(zf, content, strlen(content));
zipCloseFileInZip(zf);
}
zipClose(zf, nullptr);
std::cout << "Архив создан: example.zip\n";
return 0;
}
Пример: извлечение всех файлов из ZIP
#include <iostream>
#include <unzip.h>
int main() {
unzFile uf = unzOpen("example.zip");
if (!uf) {
std::cerr << "Не удалось открыть архив\n";
return 1;
}
unz_global_info global_info;
unzGetGlobalInfo(uf, &global_info);
for (uLong i = 0; i < global_info.number_entry; ++i) {
char filename[256];
unz_file_info file_info;
unzGetCurrentFileInfo(uf, &file_info, filename, sizeof(filename),
nullptr, 0, nullptr, 0);
if (unzOpenCurrentFile(uf) == UNZ_OK) {
char buffer[1024];
int bytes_read;
std::cout << "Извлекается: " << filename << "\n";
while ((bytes_read = unzReadCurrentFile(uf, buffer, sizeof(buffer))) > 0) {
// Здесь можно записать данные в файл
std::cout.write(buffer, bytes_read);
}
unzCloseCurrentFile(uf);
}
if (i < global_info.number_entry - 1) {