miniz
| Language | C (usable from C++) |
|---|---|
| License | MIT |
| Repository | github.com/richgel999/miniz |
| Documentation | comments in miniz_zip.h and the examples |
| Depends on | nothing |
| Read / write | yes / yes, stored and DEFLATE, ZIP64; no encryption |
miniz is a small, fast DEFLATE implementation with a zlib-compatible API plus a ZIP reader and writer. Releases include an amalgamated miniz.c + miniz.h pair that you add to your project, so it’s the easiest way to read or write ZIP files in C with no other dependency.
It supports stored and DEFLATE entries and ZIP64, extracts to memory, files or callbacks, and appends to existing archives. It doesn’t support encryption or other compression methods (bzip2, LZMA, Zstandard). All functions take a mz_zip_archive struct that you zero before use.
Installation#
Download the release zip from GitHub releases and add miniz.c and miniz.h to your build. It’s also in vcpkg and Conan:
vcpkg install miniz
Basic usage: list and extract files#
#include "miniz.h"
#include <stdio.h>
int main(void) {
mz_zip_archive zip;
mz_zip_zero_struct(&zip);
if (!mz_zip_reader_init_file(&zip, "in.zip", 0)) {
fprintf(stderr, "open failed: %s\n",
mz_zip_get_error_string(mz_zip_get_last_error(&zip)));
return 1;
}
mz_uint n = mz_zip_reader_get_num_files(&zip);
for (mz_uint i = 0; i < n; i++) {
mz_zip_archive_file_stat st;
if (!mz_zip_reader_file_stat(&zip, i, &st)) continue;
printf("%-40s %10llu -> %10llu%s\n", st.m_filename,
(unsigned long long)st.m_uncomp_size, (unsigned long long)st.m_comp_size,
st.m_is_directory ? " (dir)" : "");
}
// extract one file to memory
size_t size;
char *data = mz_zip_reader_extract_file_to_heap(&zip, "readme.txt", &size, 0);
if (data) {
fwrite(data, 1, size, stdout);
mz_free(data);
}
mz_zip_reader_end(&zip);
return 0;
}
How to create a ZIP file#
#include "miniz.h"
#include <string.h>
int write_zip(void) {
mz_zip_archive zip;
mz_zip_zero_struct(&zip);
if (!mz_zip_writer_init_file(&zip, "out.zip", 0)) return 1;
const char *text = "hello from miniz\n";
mz_bool ok = mz_zip_writer_add_mem(&zip, "hello.txt", text, strlen(text), MZ_BEST_COMPRESSION);
// add a file from disk, with no comment
ok = ok && mz_zip_writer_add_file(&zip, "docs/report.pdf", "report.pdf", NULL, 0, MZ_DEFAULT_LEVEL);
ok = ok && mz_zip_writer_finalize_archive(&zip); // writes the central directory
mz_zip_writer_end(&zip);
return ok ? 0 : 1;
}
How to extract all files to disk#
for (mz_uint i = 0; i < mz_zip_reader_get_num_files(&zip); i++) {
mz_zip_archive_file_stat st;
if (!mz_zip_reader_file_stat(&zip, i, &st) || st.m_is_directory) continue;
// st.m_filename comes from the archive: reject ".." and absolute paths
if (strstr(st.m_filename, "..") || st.m_filename[0] == '/') continue;
char out[1024];
snprintf(out, sizeof(out), "out/%s", st.m_filename);
// create parent directories of 'out' here (miniz doesn't)
mz_zip_reader_extract_to_file(&zip, i, out, 0);
}
How to add a file to an existing ZIP#
const char *text = "appended\n";
mz_bool ok = mz_zip_add_mem_to_archive_file_in_place("out.zip", "new.txt",
text, strlen(text), NULL, 0, MZ_DEFAULT_LEVEL);
This opens the archive, appends the entry and rewrites the central directory. For many files, use mz_zip_writer_init_from_reader once and add them all before finalizing.
Tips#
mz_zip_reader_init_memandmz_zip_writer_init_heapwork with archives in memory.mz_zip_reader_locate_file(&zip, "name", NULL, 0)returns the index of a file, or -1.- Define
MINIZ_NO_ZLIB_COMPATIBLE_NAMESif you also link real zlib, to avoid symbol clashes.