minizip-ng
| Language | C (usable from C++) |
|---|---|
| License | zlib license |
| Repository | github.com/zlib-ng/minizip-ng |
| Documentation | doc folder, especially mz_zip_rw.md |
| Depends on | zlib or zlib-ng; optional bzip2, liblzma, zstd, OpenSSL (or Windows / Apple crypto APIs for AES) |
| Read / write | yes / yes, ZIP64, AES and ZipCrypto, stored, DEFLATE, bzip2, LZMA, XZ, Zstandard, split archives |
minizip-ng is a rewrite of the minizip contrib code from zlib. It has two levels of API:
- the reader/writer API (
mz_zip_reader_*,mz_zip_writer_*inmz_zip_rw.h): high-level calls like “extract everything to this folder” or “add this folder recursively”, with password, progress and overwrite callbacks. - the low-level API (
mz_zip_*inmz_zip.h) with streams (mz_strm_*) for full control.
With the default MZ_COMPAT build option it also provides the old minizip unzip.h / zip.h functions (unzOpen, zipOpen…), so existing minizip code builds unchanged. Version 4.x changed mz_zip_reader_create / mz_zip_writer_create to return the handle.
Installation#
Shell
# macOS
brew install minizip-ng
# Windows / Linux (vcpkg)
vcpkg install minizip-ng
# Conan
conan install --requires=minizip-ng/4.2.1
Or add it to a CMake project with add_subdirectory / FetchContent; options like MZ_ZSTD, MZ_LZMA, MZ_OPENSSL turn features on and off.
Basic usage: list files and extract everything#
C
#include "mz.h"
#include "mz_zip.h"
#include "mz_zip_rw.h"
#include <stdio.h>
int main(void) {
void *reader = mz_zip_reader_create();
if (mz_zip_reader_open_file(reader, "in.zip") != MZ_OK) {
fprintf(stderr, "cannot open in.zip\n");
mz_zip_reader_delete(&reader);
return 1;
}
// list entries
int32_t err = mz_zip_reader_goto_first_entry(reader);
while (err == MZ_OK) {
mz_zip_file *info = NULL;
if (mz_zip_reader_entry_get_info(reader, &info) == MZ_OK) {
printf("%-40s %10lld -> %10lld\n", info->filename,
(long long)info->uncompressed_size, (long long)info->compressed_size);
}
err = mz_zip_reader_goto_next_entry(reader);
}
if (err != MZ_END_OF_LIST) fprintf(stderr, "error %d while listing\n", err);
// extract all entries into a folder
err = mz_zip_reader_save_all(reader, "out");
if (err != MZ_OK) fprintf(stderr, "extract error %d\n", err);
mz_zip_reader_close(reader);
mz_zip_reader_delete(&reader);
return err == MZ_OK ? 0 : 1;
}
How to create a ZIP from files and folders#
C
#include "mz.h"
#include "mz_zip.h"
#include "mz_zip_rw.h"
int make_zip(void) {
void *writer = mz_zip_writer_create();
mz_zip_writer_set_compress_method(writer, MZ_COMPRESS_METHOD_DEFLATE);
mz_zip_writer_set_compress_level(writer, MZ_COMPRESS_LEVEL_BEST);
int32_t err = mz_zip_writer_open_file(writer, "out.zip", 0 /*disk_size: no split*/, 0 /*append*/);
if (err == MZ_OK) {
err = mz_zip_writer_add_file(writer, "notes.txt", "notes.txt");
// add the folder "photos" recursively, keeping the "photos/" prefix
if (err == MZ_OK)
err = mz_zip_writer_add_path(writer, "photos", NULL, 1 /*include_path*/, 1 /*recursive*/);
int32_t close_err = mz_zip_writer_close(writer);
if (err == MZ_OK) err = close_err;
}
mz_zip_writer_delete(&writer);
return err;
}
How to add a file from memory#
C
const char *text = "hello from minizip-ng\n";
mz_zip_file info = {0};
info.filename = "hello.txt";
info.modified_date = time(NULL);
info.compression_method = MZ_COMPRESS_METHOD_DEFLATE;
info.flag = MZ_ZIP_FLAG_UTF8;
int32_t err = mz_zip_writer_add_buffer(writer, (void *)text, (int32_t)strlen(text), &info);
How to read one file into memory#
C
if (mz_zip_reader_locate_entry(reader, "readme.txt", 0 /*ignore_case*/) == MZ_OK) {
int32_t len = mz_zip_reader_entry_save_buffer_length(reader);
char *buf = malloc(len + 1);
if (buf && mz_zip_reader_entry_save_buffer(reader, buf, len) == MZ_OK) {
buf[len] = 0;
printf("%s\n", buf);
}
free(buf);
}
How to create and extract a password-protected ZIP (AES)#
C
// writer: set before adding entries
mz_zip_writer_set_password(writer, "my password");
mz_zip_writer_set_aes(writer, 1); // AES-256; 0 = ZipCrypto
// reader: set before extracting
mz_zip_reader_set_password(reader, "my password");
mz_zip_reader_save_all(reader, "out");
Tips#
mz_zip_reader_set_pattern(reader, "*.txt", 1)limitsgoto_first_entry/goto_next_entryandsave_allto matching names.mz_zip_reader_open_bufferopens an archive that’s already in memory.mz_zip_writer_open_file(writer, path, disk_size, 0)with a non-zerodisk_sizewrites a split archive.- The repository also builds a command-line tool,
minizip, that shows the API in action (seeminizip.c).