zlib 是業界標準的無損壓縮庫,實現 DEFLATE 演算法 (LZ77 + Huffman),廣泛用於 PNG、HTTP、Git、Zip 等格式。核心 API:
compress() / uncompress():一次性記憶體緩衝區壓縮/解壓。deflate() / inflate():流式處理,適合大檔案/網路串流。編譯鏈結:gcc -o prog prog.c -lz
// compress_file.c #include#include #include int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } FILE *fin = fopen(argv[1], "rb"); if (!fin) { perror("open input"); return 1; } // 讀取整個檔案 fseek(fin, 0, SEEK_END); long fsize = ftell(fin); fseek(fin, 0, SEEK_SET); Bytef *src = malloc(fsize); fread(src, 1, fsize, fin); fclose(fin); // 壓縮緩衝區 (最大可能輸出) uLongf dstSize = compressBound(fsize); Bytef *dst = malloc(dstSize); int ret = compress(dst, &dstSize, src, fsize); if (ret != Z_OK) { fprintf(stderr, "compress failed: %d\n", ret); free(src); free(dst); return 1; } FILE *fout = fopen(argv[2], "wb"); // 寫入原始大小 (4 bytes) + 壓縮資料 fwrite(&fsize, 4, 1, fout); fwrite(dst, 1, dstSize, fout); fclose(fout); printf("Original: %ld bytes -> Compressed: %lu bytes (%.2f%%)\n", fsize, dstSize, 100.0 * dstSize / fsize); free(src); free(dst); return 0; }
// decompress_file.c #include#include #include int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s
分塊處理,避免一次載入整個檔案:
// stream_compress.c 關鍵邏輯
#define CHUNK 16384
int deflate_file(FILE *in, FILE *out, int level) {
z_stream strm = {0};
strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL;
if (deflateInit(&strm, level) != Z_OK) return -1;
Bytef inBuf[CHUNK], outBuf[CHUNK];
int flush, ret;
do {
strm.avail_in = fread(inBuf, 1, CHUNK, in);
if (ferror(in)) { deflateEnd(&strm); return -1; }
flush = feof(in) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = inBuf;
do {
strm.avail_out = CHUNK;
strm.next_out = outBuf;
ret = deflate(&strm, flush);
if (ret == Z_STREAM_ERROR) { deflateEnd(&strm); return -1; }
size_t have = CHUNK - strm.avail_out;
if (fwrite(outBuf, 1, have, out) != have || ferror(out)) {
deflateEnd(&strm); return -1;
}
} while (strm.avail_out == 0);
} while (flush != Z_FINISH);
deflateEnd(&strm);
return ret == Z_STREAM_END ? 0 : -1;
}
| 代碼 | 常數 | 原因 |
|---|---|---|
| -1 | Z_ERRNO | 檔案 I/O 錯誤 |
| -2 | Z_STREAM_ERROR | 參數無效 (如 level 不在 0-9) |
| -3 | Z_DATA_ERROR | 輸入資料損壞/非合法壓縮流 |
| -4 | Z_MEM_ERROR | 記憶體不足 |
| -5 | Z_BUF_ERROR | 緩衝區太小 / 未提供足夠輸入 |
| -6 | Z_VERSION_ERROR | zlib 版本不匹配 |
Z_NO_COMPRESSION (0):僅封裝,無壓縮,最快。Z_BEST_SPEED (1):快速壓縮,比率較低。Z_DEFAULT_COMPRESSION (6):平衡預設值,推薦通用。Z_BEST_COMPRESSION (9):最高壓縮比,CPU 耗時最長。deflateInit2 可指定 windowBits 產生 gzip (31) 或 raw deflate (-15) 格式。deflateSetDictionary / inflateSetDictionary 針對小資料包提高壓縮比。z_stream 或使用 pigz (平行 gzip)。gzopen64 或自行管理 64 位元位移。