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

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

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

Начать курс

Работа с ZIP-архивами в C++: от простого к сложному

В современной разработке на C++ часто возникает необходимость упаковывать и распаковывать данные. Будь то сохранение конфигураций, передача логов или создание резервных копий — работа с ZIP-архивами остаётся одним из самых востребованных навыков. В этой статье мы подробно разберём две популярные библиотеки: libzip (официальная, мощная) и miniz (лёгкая, одноголовочная). Вы узнаете, как создавать, читать и модифицировать ZIP-архивы, а также получите готовые примеры кода.

Почему именно ZIP?

Формат ZIP — де-факто стандарт сжатия без потерь. Он поддерживается всеми операционными системами, позволяет хранить несколько файлов и папок, а также поддерживает шифрование и потоковую обработку. В C++ нет встроенной поддержки ZIP (кроме экспериментального <filesystem>), поэтому мы используем сторонние библиотеки.

Библиотека libzip: мощный инструмент для серьёзных задач

libzip — это кроссплатформенная библиотека на C, с отличным C++-совместимым API. Она предоставляет полный контроль над архивами: создание, чтение, изменение, удаление файлов, работа с комментариями и метаданными.

Установка libzip (Linux/macOS)

# Ubuntu/Debian
sudo apt-get install libzip-dev

# macOS (Homebrew)
brew install libzip

# Windows — через vcpkg или скачать с сайта libzip.org

Пример 1: Создание ZIP-архива

Создадим архив example.zip и добавим в него текстовый файл.

#include <zip.h>
#include <iostream>
#include <string>

int main() {
    // Открываем архив на запись (APPEND_CREATE создаст новый)
    int err = 0;
    zip_t *archive = zip_open("example.zip", ZIP_CREATE | ZIP_TRUNCATE, &err);
    if (!archive) {
        std::cerr << "Ошибка создания архива: " << err << std::endl;
        return 1;
    }

    // Данные для файла
    const char *content = "Hello from PythonLib!";
    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, "hello.txt", 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 << "Архив создан успешно!" << std::endl;
    return 0;
}

Пример 2: Распаковка всех файлов из архива

Прочитаем архив и извлечём все файлы в текущую директорию.

#include <zip.h>
#include <iostream>
#include <fstream>

int main() {
    int err = 0;
    zip_t *archive = zip_open("example.zip", ZIP_RDONLY, &err);
    if (!archive) {
        std::cerr << "Ошибка открытия архива" << 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;
        }

        // Читаем данные и записываем в файл
        char buffer[1024];
        std::ofstream out(filename, std::ios::binary);
        zip_int64_t bytes_read;
        while ((bytes_read = zip_fread(zf, buffer, sizeof(buffer))) > 0) {
            out.write(buffer, bytes_read);
        }
        out.close();
        zip_fclose(zf);
        std::cout << "Извлечён: " << filename << std::endl;
    }

    zip_close(archive);
    return 0;
}

Би

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