首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言資料壓縮與解壓縮實戰:zlib 庫完整應用指南

     編輯:關於C語言

一、zlib 簡介與編譯環境

zlib 是業界標準的無損壓縮庫,實現 DEFLATE 演算法 (LZ77 + Huffman),廣泛用於 PNG、HTTP、Git、Zip 等格式。核心 API:

  • compress() / uncompress():一次性記憶體緩衝區壓縮/解壓。
  • deflate() / inflate():流式處理,適合大檔案/網路串流。

編譯鏈結:gcc -o prog prog.c -lz

二、簡易模式:compress/uncompress 完整範例

壓縮程式

// 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  \n", argv[0]);
        return 1;
    }
    
    FILE *fin = fopen(argv[1], "rb");
    if (!fin) { perror("open input"); return 1; }
    
    uLongf origSize;
    fread(&origSize, 4, 1, fin); // 讀取原始大小
    
    fseek(fin, 0, SEEK_END);
    long compSize = ftell(fin) - 4;
    fseek(fin, 4, SEEK_SET);
    
    Bytef *comp = malloc(compSize);
    fread(comp, 1, compSize, fin);
    fclose(fin);
    
    Bytef *orig = malloc(origSize);
    int ret = uncompress(orig, &origSize, comp, compSize);
    if (ret != Z_OK) {
        fprintf(stderr, "uncompress failed: %d\n", ret);
        free(comp); free(orig);
        return 1;
    }
    
    FILE *fout = fopen(argv[2], "wb");
    fwrite(orig, 1, origSize, fout);
    fclose(fout);
    
    free(comp); free(orig);
    return 0;
}

三、進階流式處理:deflate/inflate (大檔案/記憶體受限)

分塊處理,避免一次載入整個檔案:

// 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;
}

四、常見錯誤碼與排查

代碼常數原因
-1Z_ERRNO檔案 I/O 錯誤
-2Z_STREAM_ERROR參數無效 (如 level 不在 0-9)
-3Z_DATA_ERROR輸入資料損壞/非合法壓縮流
-4Z_MEM_ERROR記憶體不足
-5Z_BUF_ERROR緩衝區太小 / 未提供足夠輸入
-6Z_VERSION_ERRORzlib 版本不匹配

五、壓縮等級選擇指南

  • Z_NO_COMPRESSION (0):僅封裝,無壓縮,最快。
  • Z_BEST_SPEED (1):快速壓縮,比率較低。
  • Z_DEFAULT_COMPRESSION (6):平衡預設值,推薦通用。
  • Z_BEST_COMPRESSION (9):最高壓縮比,CPU 耗時最長。

六、進階主題

  • gzip/zlib 包裝格式:deflateInit2 可指定 windowBits 產生 gzip (31) 或 raw deflate (-15) 格式。
  • 字典預設:deflateSetDictionary / inflateSetDictionary 針對小資料包提高壓縮比。
  • 多執行緒:zlib 本身非執行緒安全,需每執行緒獨立 z_stream 或使用 pigz (平行 gzip)。
  • 巨大檔案:64 位元系統支援 >4GB,需用 gzopen64 或自行管理 64 位元位移。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved