Работа с ZIP/архивами в C++: библиотеки и примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с 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) {                    

Рекомендаций