zlib库剖析(4):使用示例example.c

理解和使用zlib库 - 我个人的救赎 用我自己的语言解释如何理解和使用 zlib,救赎多年前发布的一篇类似的,自己的一知半解的文章. 阅读详情
    下面分析test/example.c,它示范了zlib库的各个函数的使用。

    下面代码定义要压缩的字符串、压缩时使用的字典、压缩/解压缩的内存分配策略等。

    /* example.c -- usage example of the zlib compression library 
     * Copyright (C) 1995-2006, 2011 Jean-loup Gailly. 
     * For conditions of distribution and use, see copyright notice in zlib.h 
     */  
      
    /* @(#) $Id$ */  
      
    #include "zlib.h"  
    #include <stdio.h>  
      
    #ifdef STDC  
    #  include <string.h>  
    #  include <stdlib.h>  
    #endif  
      
    #if defined(VMS) || defined(RISCOS)  
    #  define TESTFILE "foo-gz"  
    #else  
    #  define TESTFILE "foo.gz"  
    #endif  
      
    #define CHECK_ERR(err, msg) { \  
        if (err != Z_OK) { \  
            fprintf(stderr, "%s error: %d\n", msg, err); \  
            exit(1); \  
        } \  
    }  
      
    const char hello[] = "hello, hello!";  /* 字符长度为14(末尾还有一个null字符) */  
    /* "hello world" would be more standard, but the repeated "hello" 
     * stresses the compression code better, sorry... 
     */  
      
    const char dictionary[] = "hello";  
    uLong dictId; /* 字典的Adler32校验值 */  
      
    void test_deflate       OF((Byte *compr, uLong comprLen));  
    void test_inflate       OF((Byte *compr, uLong comprLen,  
                                Byte *uncompr, uLong uncomprLen));  
    void test_large_deflate OF((Byte *compr, uLong comprLen,  
                                Byte *uncompr, uLong uncomprLen));  
    void test_large_inflate OF((Byte *compr, uLong comprLen,  
                                Byte *uncompr, uLong uncomprLen));  
    void test_flush         OF((Byte *compr, uLong *comprLen));  
    void test_sync          OF((Byte *compr, uLong comprLen,  
                                Byte *uncompr, uLong uncomprLen));  
    void test_dict_deflate  OF((Byte *compr, uLong comprLen));  
    void test_dict_inflate  OF((Byte *compr, uLong comprLen,  
                                Byte *uncompr, uLong uncomprLen));  
    int  main               OF((int argc, char *argv[]));  
      
    /* Z_SOLO表示把zlib库编译成单独的不依赖第三方的库 */  
    #ifdef Z_SOLO  
      
    /* 使用自定义的内存分配策略 */  
    void *myalloc OF((void *, unsigned, unsigned));  
    void myfree OF((void *, void *));  
      
    void *myalloc(q, n, m)  
        void *q;  
        unsigned n, m;  
    {  
        q = Z_NULL;  
        return calloc(n, m);  
    }  
      
    void myfree(void *q, void *p)  
    {  
        q = Z_NULL;  
        free(p);  
    }  
      
    static alloc_func zalloc = myalloc;  
    static free_func zfree = myfree;  
      
    #else /* !Z_SOLO */  
      
    /* 使用zlib默认的内存分配策略 */  
    static alloc_func zalloc = (alloc_func)0;  
    static free_func zfree = (free_func)0;  


    下面测试compress和uncompress的用法:

    void test_compress      OF((Byte *compr, uLong comprLen,  
                                Byte *uncompr, uLong uncomprLen));  
    void test_gzio          OF((const char *fname,  
                                Byte *uncompr, uLong uncomprLen));  
      
    /* =========================================================================== 
     * 测试compress()和uncompress() 
     */  
    void test_compress(compr, comprLen, uncompr, uncomprLen)  
        Byte *compr, *uncompr;  
        uLong comprLen, uncomprLen;  
    {  
        int err;  
        uLong len = (uLong)strlen(hello)+1; /* 获取字符串长度 */  
          
        /* 压缩字符串 */  
        err = compress(compr, &comprLen, (const Bytef*)hello, len);  
        CHECK_ERR(err, "compress");  
      
        strcpy((char*)uncompr, "garbage");  
          
        /* 解压字符串 */  
        err = uncompress(uncompr, &uncomprLen, compr, comprLen);  
        CHECK_ERR(err, "uncompress");  
          
        /* 比较解压后的结果 */  
        if (strcmp((char*)uncompr, hello)) {  
            fprintf(stderr, "bad uncompress\n");  
            exit(1);  
        } else {  
            printf("uncompress(): %s\n", (char *)uncompr);  
        }  
    }  

    下面测试gzip文件的读写操作:

 /* =========================================================================== 
     * 测试.gz文件的读写操作 
     */  
    void test_gzio(fname, uncompr, uncomprLen)  
        const char *fname; /* gz文件名 */  
        Byte *uncompr;  
        uLong uncomprLen;  
    {  
    #ifdef NO_GZCOMPRESS  
        fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");  
    #else  
        int err;  
        int len = (int)strlen(hello)+1;  
        gzFile file;  
        z_off_t pos;  
      
        file = gzopen(fname, "wb");  /* 打开要写入的gz文件 */  
        if (file == NULL) {  
            fprintf(stderr, "gzopen error\n");  
            exit(1);  
        }  
        gzputc(file, 'h');  /* 写入一个字符'h' */  
        if (gzputs(file, "ello") != 4) {  /* 写入字符串"ello" */  
            fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));  
            exit(1);  
        }  
        if (gzprintf(file, ", %s!", "hello") != 8) { /* 按格式写入字符串", hello!" */  
            fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));  
            exit(1);  
        }  
        gzseek(file, 1L, SEEK_CUR); /* 读写头向前移动1字节(即添加一个0字节) */  
        gzclose(file);  /* 关闭gz文件 */  
      
        file = gzopen(fname, "rb");  /* 打开要读取的gz文件 */  
        if (file == NULL) {  
            fprintf(stderr, "gzopen error\n");  
            exit(1);  
        }  
        strcpy((char*)uncompr, "garbage");  
          
        /* 从压缩文件中读取给定大小的解压字节数 */  
        if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {  
            fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));  
            exit(1);  
        }  
        if (strcmp((char*)uncompr, hello)) {  /* 比较解压后的结果 */  
            fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);  
            exit(1);  
        } else {  
            printf("gzread(): %s\n", (char*)uncompr);  
        }  
      
        pos = gzseek(file, -8L, SEEK_CUR);  /* 读写头向后移动8字节,应该停留在第6个字符处 */  
        if (pos != 6 || gztell(file) != pos) {  /* 判断是否停留在第6个字符处 */  
            fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",  
                    (long)pos, (long)gztell(file));  
            exit(1);  
        }  
      
        if (gzgetc(file) != ' ') {  /* 从当前位置读取1个字符,应该为字符' ' */  
            fprintf(stderr, "gzgetc error\n");  
            exit(1);  
        }  
      
        if (gzungetc(' ', file) != ' ') {  /* 推回这个字符到流中 */  
            fprintf(stderr, "gzungetc error\n");  
            exit(1);  
        }  
          
        /* 从压缩文件当前位置读取指定长度的解压字节数,直到len-1个字符被读取 */  
        gzgets(file, (char*)uncompr, (int)uncomprLen);  
        if (strlen((char*)uncompr) != 7) { /* " hello!" */  
            fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));  
            exit(1);  
        }  
        if (strcmp((char*)uncompr, hello + 6)) {  
            fprintf(stderr, "bad gzgets after gzseek\n");  
            exit(1);  
        } else {  
            printf("gzgets() after gzseek: %s\n", (char*)uncompr);  
        }  
      
        gzclose(file);  /* 关闭gz文件 */  
    #endif  
    }  
      
    #endif /* Z_SOLO */ 


    下面用小缓冲区测试压缩、解压操作(deflate/deflate):

    /* =========================================================================== 
     * 测试deflate():使用小缓冲区 
     */  
    void test_deflate(compr, comprLen)  
        Byte *compr;  
        uLong comprLen;  
    {  
        z_stream c_stream; /* 压缩流 */  
        int err;  
        uLong len = (uLong)strlen(hello)+1;  
          
        /* 这三个字段要在defalteInit之前初始化 */  
        c_stream.zalloc = zalloc;  
        c_stream.zfree = zfree;  
        c_stream.opaque = (voidpf)0;  
          
        /* 初始化压缩流的状态,使用默认压缩级别 */  
        err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);  
        CHECK_ERR(err, "deflateInit");  
          
        /* 设置压缩操作的输入数据和输出缓冲区 */  
        c_stream.next_in  = (Bytef*)hello;  /* 输入缓冲区指向输入字符串 */  
        c_stream.next_out = compr;  
      
        /* 第一个循环:将flush设为Z_NO_FLUSH(表示还有输入数据未读完),将所有输入都读进去并进行压缩 
           根据avail_in和avail_out,不停地调用deflate将输入缓冲区的数据压缩 
           并写到输出缓冲区,直到输入字符串读完或输出缓冲区用完  
        */  
        while (c_stream.total_in != len && c_stream.total_out < comprLen) {  
            c_stream.avail_in = c_stream.avail_out = 1; /* 强制小缓冲区 */  
            err = deflate(&c_stream, Z_NO_FLUSH);  
            CHECK_ERR(err, "deflate");  
        }  
        /* 第二个循环:将flush设置为Z_FINISH,不再输入,让deflate()完成全部的压缩输出 
           注意因为deflate压缩时可能是异步的(为了加速压缩,读取一次输入后不一定立刻就会产生压缩输出, 
           可能读完K字节后才会产生输出),所以上一个循环可能还没产生全部输出,需要这个循环,让flush保持Z_FINISH 
           (表示输入数据已读完),多次调用deflate(),直到返回Z_STREAM_END,表示处理完全部输入并产生了全部的压缩输出  
        */  
        for (;;) {  /* 完成压缩流的刷新,仍然强制小缓冲区 */  
            c_stream.avail_out = 1;  
            err = deflate(&c_stream, Z_FINISH);  
            if (err == Z_STREAM_END) break;  
            CHECK_ERR(err, "deflate");  
        }  
      
        err = deflateEnd(&c_stream);  /* 释放压缩流的资源 */  
        CHECK_ERR(err, "deflateEnd");  
    }  
      
    /* =========================================================================== 
     * 测试inflate():使用小缓冲区 
     */  
    void test_inflate(compr, comprLen, uncompr, uncomprLen)  
        Byte *compr, *uncompr;  
        uLong comprLen, uncomprLen;  
    {  
        int err;  
        z_stream d_stream; /* 解压流 */  
      
        strcpy((char*)uncompr, "garbage");  
      
        /* 这些个字段要在infalteInit之前初始化 */  
        d_stream.zalloc = zalloc;  
        d_stream.zfree = zfree;  
        d_stream.opaque = (voidpf)0;  
      
        d_stream.next_in  = compr;  /* 设置输入缓冲区 */  
        d_stream.avail_in = 0;  
        d_stream.next_out = uncompr;  /* 设置输出缓冲区 */  
      
        /* 初始化解压流的状态 */  
        err = inflateInit(&d_stream);  
        CHECK_ERR(err, "inflateInit");  
      
        /* 只需一个循环:根据avail_in和avail_out,不停地调用inflate将输入缓冲区的数据 
           解压,直到返回Z_STREAM_END,表示处理完全部输入并产生了全部的解压输出 
           这里与flush参数是否为Z_FINISH无关 
        */  
        while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {  
            d_stream.avail_in = d_stream.avail_out = 1; /* 强制小缓冲区 */  
            err = inflate(&d_stream, Z_NO_FLUSH);  
            if (err == Z_STREAM_END) break;  
            CHECK_ERR(err, "inflate");  
        }  
      
        err = inflateEnd(&d_stream);  /* 释放解压流的资源 */  
        CHECK_ERR(err, "inflateEnd");  
      
        if (strcmp((char*)uncompr, hello)) {  /* 比较解压后的数据 */  
            fprintf(stderr, "bad inflate\n");  
            exit(1);  
        } else {  
            printf("inflate(): %s\n", (char *)uncompr);  
        }  
    }  

    下面使用大缓冲区测试压缩、解压操作(deflate/deflate):

    /* =========================================================================== 
     * 测试deflate():使用大缓冲区和动态改变的压缩级别 
     */  
    void test_large_deflate(compr, comprLen, uncompr, uncomprLen)  
        Byte *compr, *uncompr;  
        uLong comprLen, uncomprLen;  
    {  
        z_stream c_stream; /* 压缩流 */  
        int err;  
      
        /* 这三个字段要在defalteInit之前初始化 */  
        c_stream.zalloc = zalloc;  
        c_stream.zfree = zfree;  
        c_stream.opaque = (voidpf)0;  
      
        /* 初始化压缩流的状态,使用最快速度压缩 */  
        err = deflateInit(&c_stream, Z_BEST_SPEED);  
        CHECK_ERR(err, "deflateInit");  
      
        c_stream.next_out = compr;  
        c_stream.avail_out = (uInt)comprLen;  
      
        /* 这里,uncompr几乎都为0,因此可以很好地被压缩 */  
        c_stream.next_in = uncompr;  
        c_stream.avail_in = (uInt)uncomprLen;  
        err = deflate(&c_stream, Z_NO_FLUSH); /* 压缩输入数据 */  
        CHECK_ERR(err, "deflate");  
        if (c_stream.avail_in != 0) {  
            fprintf(stderr, "deflate not greedy\n");  
            exit(1);  
        }  
      
        /* 把已压缩的数据转换成未压缩: */  
          
        /* 设置流的压缩级别(为未压缩)和压缩策略 */  
        deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);  
        c_stream.next_in = compr;  
        c_stream.avail_in = (uInt)comprLen/2;  
        err = deflate(&c_stream, Z_NO_FLUSH);  
        CHECK_ERR(err, "deflate");  
      
        /* 转换回压缩模式(最高压缩率): */  
        deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);  
        c_stream.next_in = uncompr;  
        c_stream.avail_in = (uInt)uncomprLen;  
        err = deflate(&c_stream, Z_NO_FLUSH);  
        CHECK_ERR(err, "deflate");  
      
        /* 流刷新,产生全部压缩输出 */  
        err = deflate(&c_stream, Z_FINISH);  
        if (err != Z_STREAM_END) {  
            fprintf(stderr, "deflate should report Z_STREAM_END\n");  
            exit(1);  
        }  
        err = deflateEnd(&c_stream);  /* 释放流的资源 */  
        CHECK_ERR(err, "deflateEnd");  
    }  
      
    /* =========================================================================== 
     * 测试inflate():使用大缓冲区 
     */  
    void test_large_inflate(compr, comprLen, uncompr, uncomprLen)  
        Byte *compr, *uncompr;  
        uLong comprLen, uncomprLen;  
    {  
        int err;  
        z_stream d_stream; /* 解压流 */  
      
        strcpy((char*)uncompr, "garbage");  
      
        /* 这些个字段要在infalteInit之前初始化 */  
        d_stream.zalloc = zalloc;  
        d_stream.zfree = zfree;  
        d_stream.opaque = (voidpf)0;  
      
        d_stream.next_in  = compr;  
        d_stream.avail_in = (uInt)comprLen;  
      
        /* 初始化解压流 */  
        err = inflateInit(&d_stream);  
        CHECK_ERR(err, "inflateInit");  
      
        /* 解压 */  
        for (;;) {  
            d_stream.next_out = uncompr;            /* 抛弃输出 */  
            d_stream.avail_out = (uInt)uncomprLen;  
            err = inflate(&d_stream, Z_NO_FLUSH);  /* 解压输入数据 */  
            if (err == Z_STREAM_END) break;  
            CHECK_ERR(err, "large inflate");  
        }  
      
        err = inflateEnd(&d_stream);  
        CHECK_ERR(err, "inflateEnd");  
      
        if (d_stream.total_out != 2*uncomprLen + comprLen/2) {  
            fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);  
            exit(1);  
        } else {  
            printf("large_inflate(): OK\n");  
        }  
    }  



    下面使用完全刷新模式测试压缩操作deflate:

/* =========================================================================== 
     * 测试deflate():使用完全刷新 
     */  
    void test_flush(compr, comprLen)  
        Byte *compr;  
        uLong *comprLen;  
    {  
        z_stream c_stream; /* 压缩流 */  
        int err;  
        uInt len = (uInt)strlen(hello)+1;  
      
        c_stream.zalloc = zalloc;  
        c_stream.zfree = zfree;  
        c_stream.opaque = (voidpf)0;  
      
        err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);  
        CHECK_ERR(err, "deflateInit");  
      
        c_stream.next_in  = (Bytef*)hello;  
        c_stream.next_out = compr;  
        c_stream.avail_in = 3;  
        c_stream.avail_out = (uInt)*comprLen;  
        /* 使用完全刷新来压缩字符串 */  
        err = deflate(&c_stream, Z_FULL_FLUSH);  
        CHECK_ERR(err, "deflate");  
      
        compr[3]++; /* 在第一个压缩块中强制产生一个错误 */  
        c_stream.avail_in = len - 3;  
      
        err = deflate(&c_stream, Z_FINISH);  
        if (err != Z_STREAM_END) {  
            CHECK_ERR(err, "deflate");  
        }  
        err = deflateEnd(&c_stream);  
        CHECK_ERR(err, "deflateEnd");  
      
        *comprLen = c_stream.total_out;  
    }  


    下面测试同步方式的解压操作inflateSync:
    /* =========================================================================== 
     * Test inflateSync() 
     */  
    void test_sync(compr, comprLen, uncompr, uncomprLen)  
        Byte *compr, *uncompr;  
        uLong comprLen, uncomprLen;  
    {  
        int err;  
        z_stream d_stream; /* 解压流 */  
      
        strcpy((char*)uncompr, "garbage");  
      
        d_stream.zalloc = zalloc;  
        d_stream.zfree = zfree;  
        d_stream.opaque = (voidpf)0;  
      
        d_stream.next_in  = compr;  /* 设置输入缓冲区 */  
        d_stream.avail_in = 2; /* 只读取zlib头部信息 */  
      
        err = inflateInit(&d_stream);  
        CHECK_ERR(err, "inflateInit");  
      
        d_stream.next_out = uncompr;  /* 设置输出缓冲区 */  
        d_stream.avail_out = (uInt)uncomprLen;  
      
        inflate(&d_stream, Z_NO_FLUSH);  
        CHECK_ERR(err, "inflate");  
      
        d_stream.avail_in = (uInt)comprLen-2;   /* 读取所有压缩数据 */  
        err = inflateSync(&d_stream);           /* 但忽略损坏的部分 */  
        CHECK_ERR(err, "inflateSync");  
      
        err = inflate(&d_stream, Z_FINISH);  /* 完成解压 */  
        if (err != Z_DATA_ERROR) {  
            fprintf(stderr, "inflate should report DATA_ERROR\n");  
            /* 因为不正确的adler32 */  
            exit(1);  
        }  
        err = inflateEnd(&d_stream);  
        CHECK_ERR(err, "inflateEnd");  
      
        printf("after inflateSync(): hel%s\n", (char *)uncompr);  
    }  

  

    下面用预设的字典测试压缩、解压操作(deflate/inflate):

    /* =========================================================================== 
     * 测试:deflate():使用预设的字典 
     */  
    void test_dict_deflate(compr, comprLen)  
        Byte *compr;  
        uLong comprLen;  
    {  
        z_stream c_stream; /* 压缩流 */  
        int err;  
      
        c_stream.zalloc = zalloc;  
        c_stream.zfree = zfree;  
        c_stream.opaque = (voidpf)0;  
      
        err = deflateInit(&c_stream, Z_BEST_COMPRESSION);  
        CHECK_ERR(err, "deflateInit");  
      
        /* 设置压缩流要使用的字典 */  
        err = deflateSetDictionary(&c_stream,  
                    (const Bytef*)dictionary, (int)sizeof(dictionary));  
        CHECK_ERR(err, "deflateSetDictionary");  
      
        dictId = c_stream.adler;  /* 得到字典的Alder32校验值 */  
        c_stream.next_out = compr;  
        c_stream.avail_out = (uInt)comprLen;  
      
        c_stream.next_in = (Bytef*)hello; /* 输入要压缩的字符串 */  
        c_stream.avail_in = (uInt)strlen(hello)+1;  
      
        /* 直接进行压缩 */  
        err = deflate(&c_stream, Z_FINISH);  
        if (err != Z_STREAM_END) {  
            fprintf(stderr, "deflate should report Z_STREAM_END\n");  
            exit(1);  
        }  
        err = deflateEnd(&c_stream);  
        CHECK_ERR(err, "deflateEnd");  
    }  
      
    /* =========================================================================== 
     * 测试inflate():使用预设的字典 
     */  
    void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)  
        Byte *compr, *uncompr;  
        uLong comprLen, uncomprLen;  
    {  
        int err;  
        z_stream d_stream; /* 解压流 */  
      
        strcpy((char*)uncompr, "garbage");  
      
        d_stream.zalloc = zalloc;  
        d_stream.zfree = zfree;  
        d_stream.opaque = (voidpf)0;  
      
        d_stream.next_in  = compr;  
        d_stream.avail_in = (uInt)comprLen;  
      
        err = inflateInit(&d_stream);  
        CHECK_ERR(err, "inflateInit");  
      
        d_stream.next_out = uncompr;  
        d_stream.avail_out = (uInt)uncomprLen;  
      
        for (;;) {  /* 解压 */  
            err = inflate(&d_stream, Z_NO_FLUSH);  
            if (err == Z_STREAM_END) break;  
            if (err == Z_NEED_DICT) {  /* 如果需要字典 */  
                if (d_stream.adler != dictId) {  /* 校验是否与压缩时的字典值一致 */  
                    fprintf(stderr, "unexpected dictionary");  
                    exit(1);  
                }  
                /* 设置解压需要的字典 */  
                err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,  
                                           (int)sizeof(dictionary));  
            }  
            CHECK_ERR(err, "inflate with dict");  
        }  
      
        err = inflateEnd(&d_stream);  
        CHECK_ERR(err, "inflateEnd");  
      
        if (strcmp((char*)uncompr, hello)) {  /* 比较解压后的字符串 */  
            fprintf(stderr, "bad inflate with dict\n");  
            exit(1);  
        } else {  
            printf("inflate with dictionary: %s\n", (char *)uncompr);  
        }  
    }  


    下面是命令行程序:

    

/* =========================================================================== 
 * Usage:  example [output.gz  [input.gz]] 
 */  
  
int main(argc, argv)  
    int argc;  
    char *argv[];  
{  
    Byte *compr, *uncompr;  
    uLong comprLen = 10000*sizeof(int); /* 在MSDOS上不会溢出 */  
    uLong uncomprLen = comprLen;  
    static const char* myVersion = ZLIB_VERSION;  
  
    /* 检查zlib版本是否一致 */  
    if (zlibVersion()[0] != myVersion[0]) {  
        fprintf(stderr, "incompatible zlib version\n");  
        exit(1);  
  
    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {  
        fprintf(stderr, "warning: different zlib version\n");  
    }  
  
    /* 打印版本和zlib编译信息 */  
    printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",  
            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());  
  
    /* 分配输入、输出缓冲区的内存 */  
    compr    = (Byte*)calloc((uInt)comprLen, 1);  
    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);  
    /* 清空compr和uncompr,以避免读到未初始化的数据,并且确保uncompr能很好 
     * 地被压缩 
     */  
    if (compr == Z_NULL || uncompr == Z_NULL) {  
        printf("out of memory\n");  
        exit(1);  
    }  
  
    /* 下面运行各个测试函数 */  
#ifdef Z_SOLO  
    argc = strlen(argv[0]);  
#else  
    test_compress(compr, comprLen, uncompr, uncomprLen);  
  
    test_gzio((argc > 1 ? argv[1] : TESTFILE),  
              uncompr, uncomprLen);  
#endif  
  
    test_deflate(compr, comprLen);  
    test_inflate(compr, comprLen, uncompr, uncomprLen);  
  
    test_large_deflate(compr, comprLen, uncompr, uncomprLen);  
    test_large_inflate(compr, comprLen, uncompr, uncomprLen);  
  
    test_flush(compr, &comprLen);  
    test_sync(compr, comprLen, uncompr, uncomprLen);  
    comprLen = uncomprLen;  
  
    test_dict_deflate(compr, comprLen);  
    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);  
  
    /* 释放缓冲区资源 */  
    free(compr);  
    free(uncompr);  
  
    return 0;  
}  
  原文地址:http://blog.youkuaiyun.com/zhoudaxia/article/details/8039540
zlib的使用小例 本实例使用zlib中的主要压缩与解压函数compress\uncompress,对文件进行压缩和解压,对于使用zlib的初学者有一定的帮助。 立即下载

相关推荐

ESP32-S3开发环境避坑指南:VS Code+ESP-IDF离线安装全流程(附国内镜像加速)

本文提供了一份详细的ESP32-S3开发环境离线安装指南,重点解决网络依赖问题。通过整合国内镜像加速,手把手教你完成VS Code、ESP-IDF框架、工具链及Python依赖的本地化部署,实现稳定、可重复的开发环境搭建,大幅提升IoT开发效率。

peach的博客 961

Zlib压缩类库使用

zlib 是通用的压缩库,提供了一套 in-memory 压缩和解压函数,并能检测解压出来的数据的完整性(integrity)。zlib 也支持读写 gzip (.gz) 格式的文件。下面介绍两个最有用的函数——compress 和 uncompress。   int compress(Bytef *dest, uLongf *destLen, const Bytef *source,

rfkl001的专栏 2037

警惕AI依赖:如何避免数字水蛭侵蚀你的认知能力

在人工智能技术日益普及的今天,人机协作已成为现代工作流的核心范式。其原理在于通过算法模型辅助人类完成信息处理、内容生成等任务,从而提升效率。然而,过度依赖AI可能导致认知卸载,引发思考能力退化等潜在风险。从技术价值看,AI的核心在于增强而非替代人类智能,关键在于建立健康的协作模式。在应用场景上,无论是编程开发、内容创作还是决策分析,用户都需警惕工具依赖对深度工作、创造性思维和决策责任的侵蚀。本文聚焦于识别AI依赖的早期信号,并提供构建分阶段使用流程、将AI作为质疑者等具体策略,旨在帮助读者守护核心认知能力,

weixin_30240349的博客 624

zlib库使用简单讲解

&#13; &#13; &#13; &#13; &#13; &#13; &#13; 1.zlib库简介   zlib 是通用的压缩库,提供了一套 in-memory 压缩和解压函数,并...

Linux知识积累 4万+

红外通信不止遥控器:手把手教你用2ASK调制实现语音+温度数据同传

本文详细介绍了如何利用2ASK调制技术实现红外通信系统,同时传输语音和温度数据。通过STM32F103C8T6微控制器和DS18B20温度传感器的硬件设计,结合2ASK调制原理,展示了系统的完整实现方案。文章还提供了调试优化建议,适合电子爱好者和通信工程学生实践学习。

weixin_42531588的博客 387

eDP、DP与HDMI——现代显示接口的核心解析

eDP、DP和HDMI各有千秋:eDP以嵌入式设备的低功耗见长,DP凭借开放生态和高带宽成为专业领域首选,而HDMI则依靠庞大的消费电子生态稳居家庭市场。未来,随着Type-C接口的普及和超高清内容的爆发,三者的技术边界可能进一步融合,但各自的核心优势仍将长期共存。对于用户而言,选择接口需基于设备需求——游戏玩家青睐HDMI的VRR,设计师依赖DP的多屏扩展,而轻薄本则离不开eDP的紧凑设计。

麟的博客 8407

第三方库介绍——zlib库

第三方库介绍——zlib库

NRWHF的博客 3万+

基于CANopenNode协议栈在正点原子探索者开发板上进行移植

配置好之后进行采用keil IDE进行代码生成即可,还需要进行CANopenNode的代码集成,并参照demo进行代码移植。发送完成后心跳包以1s的周期重新开始发送。正点原子的开发板引出的是CAN1接口。这里的心跳时间间隔设置为100ms。则将心跳包周期设置为0。

wangfandashe的博客 4693

C/C++ Zlib库封装MyZip压缩类

Zlib是一个开源的数据压缩库,提供了一种通用的数据压缩和解压缩算法。它最初由Jean-Loup Gailly和Mark Adler开发,旨在成为一个高效、轻量级的压缩库,其被广泛应用于许多领域,包括网络通信、文件压缩、数据库系统等。其压缩算法是基于DEFLATE算法,这是一种无损数据压缩算法,通常能够提供相当高的压缩比。 在软件开发中,文件的压缩和解压缩是一项常见的任务,而ZIP是一种被广泛应用的压缩格式。为了方便地处理ZIP压缩和解压缩操作,开发者通常使用各种编程语言和库来实现这些功能。本文将聚焦于一

微软技术分享 5421

【施磊】C++课程笔记目录

【C++编程】施磊老师C++笔记目录

GeniusAng的博客 4122

零基础NPU固件开发学习路线--1.4 学习路线与工具链:编译器、仿真器、调试器、烧录工具

本文系统介绍了NPU固件开发的学习路径与工具链。学习路线分为四个阶段:基础认知、环境搭建、模块开发和联调量产。重点讲解了交叉编译器、代码管理工具、调试器和烧录工具等核心工具链的使用方法。文章强调工具链在NPU固件开发中的关键作用,详细阐述了从代码同步到固件烧录的全流程开发闭环,为开发者提供了一条从零基础到独立开发的完整学习路径。

MHD0815的博客 112

zlib库剖析(3):使用示例zpipe.c

我们常常疑惑不知道怎么样使用deflate()和inflate()。用户想知道应该在什么时候提供更多输入,什么时候使用更多输出,怎么处理Z_BUF_ERROR,怎么确保处理正确地终止,等等。example目录下有一个简单的例程zpipe.c,示范了使用deflate()和inflat...

chuifuhuo6864的博客 385

YOLOv8极速瘦身实战:LAMP剪枝让模型又快又准

一个庞大的模型虽然强大,但在实际部署,尤其是资源受限的边缘设备(如无人机、移动电话、嵌入式系统)上,却面临着严峻的挑战:高昂的内存占用、巨大的计算量以及随之而来的高延迟和高能耗。本教程从LAMP剪枝的深刻理论出发,详细解释了它如何通过最小化最坏情况下的L2失真,并借助巧妙的数学简化,最终推导出一种高效、无超参数、层自适应的剪枝策略。它如同为臃肿的模型进行一次精准的“瘦身手术”,通过移除网络中冗余或不重要的权重、神经元甚至整个结构,来显著降低模型的参数量和计算量(FLOPs),从而实现推理加速和资源节约。

FJN110的博客 257

WasmEdge wasmedge-zlib 插件实战:从 WIT 接口到 C++ 示例的完整构建与运行指南

本文以 WasmEdge 仓库中的 [wasmedge-zlib 示例](https://link.gitcode.com/i/36cf07b8202c6ea261ac669ba18ca7d3) 为核心,完整讲解如何让 WebAssembly 模块直接复用宿主环境的 zlib 压缩库。你将掌握环境准备(Emscripten、WasmEdge Runtime、插件、wit-bindgen)、`Mak

gitblog_00731的博客 67

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

OSS-Fuzz 项目结构完全指南:从 project.yaml 到 build.sh 的 fuzz 集成实战

本文以 OSS-Fuzz 仓库中 `projects/` 目录为研究对象,系统讲解一个 OSS-Fuzz 项目由哪些文件构成、每个文件承担什么职责、关键字段与构建环境变量如何工作,并结合仓库内真实项目(zlib、example)的配置文件与构建脚本进行源码级剖析。读完本文,你将能够独立理解任意 OSS-Fuzz 项目目录的组成,并掌握为开源软件编写 `project.yaml`、`Dockerfi

gitblog_00121的博客 401

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

深入解析 PocketSocket:用 Objective-C 打造符合 RFC6455 的 WebSocket 客户端与服务端

PocketSocket 是一个用 Objective-C 编写、面向 iOS 与 macOS 的 WebSocket 库,目标是让开发者用原生的 NSStream / CFSocket 技术栈构建实时通信应用。本篇文章围绕仓库内 [Pods/PocketSocket/README.md](https://link.gitcode.com/i/f507b9ac5623d839bf351af16a4

gitblog_00875的博客 1056

GitHack原理与防御:从.git泄露看源代码安全攻防实战

在软件开发生命周期中,版本控制系统是代码管理的核心基础设施,其中Git作为分布式版本控制的事实标准,其工作原理基于对象存储和引用机制。Git通过SHA-1哈希算法将文件内容、目录结构和提交历史转换为唯一标识,存储在.git目录的objects子目录中,形成完整的版本历史图谱。这种设计虽然高效,但若配置不当,可能引发严重的安全风险——当.git目录被意外部署到Web可访问路径时,攻击者可以利用目录结构可预测的特性,通过自动化工具递归下载所有Git对象,完全重构项目源代码。从技术价值看,理解这一攻击链不仅有助于

weixin_34068198的博客 393

gRPC Bazel 构建支持详解:WORKSPACE 依赖接入、版本策略与源码实现剖析

gRPC 仓库的主构建系统是 Bazel,C++、Python 与 Objective-C 三类构建规则均以 Bazel 定义为源头,CMake 等其他构建系统的规则也是从 Bazel 定义生成的。本文基于 [bazel_support.md](https://link.gitcode.com/i/5fc00b7bd345980fa39417e2216e7e08) 的官方说明,结合 [bazel/

gitblog_00545的博客 461

把一份背包数据装进 NBT:KNBT 在鸿蒙 KMP上的标签与压缩实验

最后执行十六项设备内检查,覆盖三种包装的往返、Unicode 文本、长整数、空 Compound、整数数组、规范化幂等、包装头识别、语法拒绝、跨缓冲块数据、截断与校验损坏以及反复释放。序列化核心与 Okio 使用对应的 OHOS 发行依赖,版本、来源及摘要保留在源码目录,避免出现“同名依赖能下载,目标架构却对不上”的情况。但把数据保存下来,再交给另一个程序读取,问题就换了一种问法:生命值原来是短整数,开关原来是一个字节,余额用了长整数,这些区别经过一次编码和解码之后还能不能保留?

程序猿追的博客 2081

QUANTAXIS 2.1.0 Rust 集成完全指南:QARS2 高性能核心的安装、使用与原理剖析

QUANTAXIS 在 2.1.0 版本中引入 Rust 集成(QARS2 / QUANTAXIS Rust),将数据计算、账户撮合与回测引擎迁移到 Rust 侧,目标是对纯 Python 实现获得 10~100 倍的性能提升。本文以 [doc/advanced/rust-integration.md](https://link.gitcode.com/i/edd144bcdd7bbd801713

gitblog_00899的博客 315

C/C++工程师的HTTP协议实战指南:从字节流到高性能服务架构

HTTP协议作为应用层通信的基石,定义了客户端与服务器之间基于请求-响应的交互模型。其核心原理是在TCP连接之上,通过标准化的文本格式(起始行、头部、主体)传输数据,支持多种方法(如GET、POST)和状态码来表征操作语义。该协议的技术价值在于为分布式系统提供了统一、无状态的通信标准,是实现Web服务、API接口和微服务架构的关键。在实际的工程实践中,尤其是在高并发后台服务场景下,深入理解HTTP协议的细节,如连接复用、报文解析和状态管理,对于构建稳定、高效的网络通信层至关重要。本文将结合C/C++开发视角

weixin_34259232的博客 362
上一篇: zlib库剖析(3):使用示例zpipe.c
下一篇: MSBuild入门
cbbbc
博客等级 码龄15年 609粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值