zlib 库的压缩解压缩操作

        zlib 是通用的压缩库,提供了一套 in-memory 压缩和解压函数,并能检测解压出来的数据的完整性(integrity) zlib 也支持读写 gzip (.gz) 格式的文件。

linux 下的 zlib 库安装

第一步:zlib 的下载(不建议在共享目录中操作)
wget http : //www.zlib.net/zlib-1.2.11.tar.gz
第二步:解压
tar zxvf zlib-1.2.11.tar.gz
第三步:进入解压好的文件中
cd zlib-1.2.11
第四步:编译-相关参数配置,软件安装位置,支持软件设置,软件依赖检查,生成编译 对应的工具文件。
./configure
第五步:根据 configure 的配置信息生成“二进制文件”
make
第六步:把生成的二进制文件复制到系统指定目录
make install
注意:使用 zlib 中的 api 在编译时要加-lz 指定库文件

数据压缩 API(compress)

头文件:
#include <zlib.h>
函数原型:
int compress(Bytef *dest, uLongf *destLen, const Bytef *source,uLong sourceLen);
作用:
        compress 函数将 source 缓冲区中的内容压缩到 dest 缓冲区。sourceLen 表示 source 缓冲
区的大小(以字节计)。注意函数的第二个参数 destLen 是传址调用。当调用函数时,destLen表示 dest 缓冲区的大小,destLen>(sourceLen+12)*100.1%。当函数退出后,destLen 表示压缩后缓冲区的实际大小。此时 destLen/sourceLen 正好是压缩率。
参数含义:
        dest: 用来保存压缩后数据的内存地址
        destLen:dest 的大小,当函数返回后,该值表示压缩后存入 dest 缓冲区中实际的字节大 小
        source:用来保存待压缩的数据
        sourceLen:source 空间的大小
返回值:
        compress 若成功,则返回 Z_OK;若没有足够内存,则返回 Z_MEM_ERROR;若输出缓冲区不够大,则返回 Z_BUF_ERROR。
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_NEED_DICT 2
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
#define Z_VERSION_ERROR (-6)

数据解压缩 API(uncompress)

头文件:
#include <zlib.h>
函数原型:
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,uLong sourceLen);
作用:
        uncompress 函数将 source 缓冲区的内容解压缩到 dest 缓冲区。sourceLen 是 source 缓冲 区的大小(以字节计)。注意函数的第二个参数 destLen 是传址调用。当调用函数时,destLe 表示 dest 缓冲区的大小,dest 缓冲区要足以容下解压后的数据。在进行解压缩时,需要提前知道被压缩的数据解压出来会有多大。这就要求在进行压缩之前,保存原始数据的大小(也就是解压后的数据的大小)。这不是 zlib 函数库的功能,需要我们做额外的工作。当函数退出后,destLen 是解压出来的数据的实际大小。
参数含义:
        dest: 用来保存解压缩后数据的内存地址
        destLen:dest 的大小,当函数返回后,该值表示解压缩后存入 dest 缓冲区中实际的字节大小
        source:用来保存待解压缩的数据
        sourceLen:source 空间的大小
返回值:
        uncompress 若成功,则返回 Z_OK ;若没有足够内存,则返回 Z_MEM_ERROR;若输出缓冲区不够大,则返回 Z_BUF_ERROR。若输入数据有误,则返回 Z_DATA_ERROR。

压缩长度预测 API(compressBound)

头文件:
#include <zlib.h>
函数原型:
unsigned long compressBound(unsigned long sourceLen);
作用:
        compressBound 函数可以对 compress 压缩后的数据做一个最大大小预估,因为有可能压缩
后的数据比压缩前的数据要大,所以防止在创建保存压缩数据空间时造成的空间不足的问题,就有了空间预估的操作。
参数含义:
        sourceLen: 待压缩的数据的长度
返回值:
        返回压缩后最大的数据长度

使用示例

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <zlib.h>
int main(int argc, char* argv[])
{
    char text[] = "zlib compress and uncompress test\nturingo@163.com\n2012-11-05\n";
    uLong tlen = strlen(text) + 1; /* 需要把字符串的结束符'\0'也一并处理 */
    char* buf = NULL;
    uLong blen;
    /* 计算缓冲区大小,并为其分配内存 */
    blen = compressBound(tlen); /* 压缩后的长度是不会超过 blen 的 */
    if((buf = (char*)malloc(sizeof(char) * blen)) == NULL)
    {
        printf("no enough memory!\n");
        return -1;
    }

    /* 压缩 */
    if(compress(buf, &blen, text, tlen) != Z_OK)
    {
        printf("compress failed!\n");
        return -1;
    }

    /* 解压缩 */
    if(uncompress(text, &tlen, buf, blen) != Z_OK) 
    {
        printf("uncompress failed!\n");
        return -1;
    }

    /* 打印结果,并释放内存 */
    printf("%s", text);
    if(buf != NULL)
    {
        free(buf);
        buf = NULL;
    }
    printf("源数据长度:%ld\n",tlen);
    printf("压缩后数据长度:%ld\n",blen);
    printf("压缩率%f%%\n",(float)blen/(float)tlen*100);
    return 0;
}

gzip(.gz)文件打开函数(gzopen) 

头文件:
#include <zlib.h>
函数原型:
gzFile gzopen(const char *path, const char *mode);
作用:
        以 mode 方式打开名为 path 一个 gzip 压缩文件(.gz)。
参数含义:
        path: gzip 文件的名字
        mode:打开方式,和 fopen 的参数相同
返回值:
        成功返回一个 gzFile 流指针,不用去在意 gzFile 是啥,它是一个文件流结构体,和
File 差不多,失败返回 NULL
typedef struct gzFile_s * gzFile ; /* semi-opaque gzip file descriptor */

gzip(.gz)文件关闭函数(gzclose)

头文件:
#include <zlib.h>
函数原型:
int gzclose(gzFile file);
作用:
        关闭 file 文件流指向的压缩文件。
参数含义:
        file: gzFile 文件流
返回值:
        成功返回 Z_OK, 如果文件无效,gzclose 将返回 Z_STREAM_ERROR(-2), Z_ERRNO()(文 件操作错误),Z_MEM_ERROR(内存不足),Z_BUF_ERROR(最后一次读取在 gzip 流中结束)

gzip(.gz)文件写函数

gzputc 函数

头文件:
#include <zlib.h>
函数原型:
int gzputc(gzFile file, int c);
作用:
        将字符 c 写入压缩文件流 file 中
参数含义:
        file: gzFile 文件流
        c:待写入的字符数据(ASCII 码形式)
返回值:
        成功返回写入的字符,失败返回-1

gzputs 函数

头文件:
#include <zlib.h>
函数原型:
int gzputs(gzFile file, const char *s);
作用:
        将字符串 s 写入压缩文件流 file 中。
参数含义:
        file: gzFile 文件流
        s:待写入的字符串数据
返回值:
        成功返回写入的字符数,失败返回-1

gzprintf 函数

头文件:
#include <zlib.h>
函数原型:
int gzprintf(gzFile file, const char *format, ...);
作用:
        将格式化字符串 format 写入压缩文件流 file 中。
参数含义:
        file: gzFile 文件流
        format:待写入的格式化字符串数据
返回值:
        成功返回写入的字符数,失败返回-1

gzwrite 函数

头文件:
#include <zlib.h>
函数原型:
int gzwrite(gzFile file,voidpc buf, unsigned len);
作用:
        将 buf 内存的前 len 个字节写入 file 流中。
参数含义:
        file: gzFile 文件流
        buf:待写入的内存数据
        len:待写入的字节数
返回值:
        成功返回实际写入的字符数,失败返回-1

gzip(.gz)文件读函数

gzgetc 函数

头文件:
#include <zlib.h>
函数原型:
int gzgetc(gzFile file);
作用:
        从 file 流指向的压缩文件中读取一个字符,返回它的 ASCII 码
参数含义:
        file: gzFile 文件流
返回值:
        成功返回读取字符的 ASCII 码,失败返回-1

gzgets 函数

头文件:
#include <zlib.h>
函数原型:
int gzgets(gzFile file,char *buf, int len);
作用:
        从 file 流指向的压缩文件中读取一个字符串
参数含义:
        file: gzFile 文件流
        buf:保存字符串的空间地址
        len:读取字符串的长度
返回值:
        成功返回实际读取字符的个数,失败返回-1

gzread 函数

头文件:
#include <zlib.h>
函数原型:
int gzgets(gzFile file, voidp buf, unsigned len);
作用:
        从 file 流指向的压缩文件中读取一个 len 个字节数据放到 buf 指向的内存中
参数含义:
        file: gzFile 文件流
        buf:保存数据的空间地址
        len:读取数据的字节长度
返回值:
        成功返回实际读取字符的个数,失败返回-1

gzip(.gz)文件指针定位函数

gztell 函数

头文件:
#include <zlib.h>
函数原型:
int gztell(gzFile file);
作用:
        返回 file 流指向的文件指针距离文件开头位置的距离
参数含义:
        file: gzFile 文件流
返回值:
        返回文件指针距离文件开头的字节数,失败返回-1

gzseek 函数

头文件:
#include <zlib.h>
函数原型:
z_off_t gzseek(gzFile file,z_off_t offset, int whence);
作用:
        指定 file 指向的文件指针基于 whence 偏移 offset 个字节
参数含义:
        file: gzFile 文件流
        offset:偏移量
        whence:偏移起始位置
                SEEK_SET:基于文件开头定位
                SEEK_CUR:基于当前位置定位
                SEEK_END:基于文件末尾定位
返回值:
        成功返回文件开头距离现在位置的字节数,失败返回-1
备注:
        z_off_t 是有符号长整型

gzrewind 函数

头文件:
#include <zlib.h>
函数原型:
int gzrewind(gzFile file);
作用:
        将 file 指向的文件指针偏移到文件开头
参数含义:
        file: gzFile 文件流
返回值:
        忽略

使用示例

#include <stdio.h>
#include <string.h>
#include <zlib.h>
unsigned long file_size(char *filename) //计算文件大小
{
    FILE *pFile = fopen(filename, "rb");
    fseek(pFile, 0, SEEK_END); //偏移到文件尾
    unsigned long size = ftell(pFile); //读取文件指针到开头的字节数
    fclose(pFile);
    return size;
}

int decompress_one_file(char *infilename, char *outfilename)
{
    int num_read = 0; 
    char buffer[128] = {0};
    gzFile infile = gzopen(infilename, "rb");
    FILE *outfile = fopen(outfilename, "wb");
    if (!infile || !outfile)
    {
        return -1;
    }
    while ((num_read = gzread(infile, buffer, sizeof(buffer))) > 0) 
    {
        fwrite(buffer, 1, num_read, outfile);
        memset(buffer,0,128);
    }
    gzclose(infile);
    fclose(outfile);
    return 0;
}

int compress_one_file(char *infilename, char *outfilename)
{
    int num_read = 0; //保存读取到的字节数
    char inbuffer[128] = {0}; //保存读取的文件数据
    unsigned long total_read = 0; //保存源文件大小
    FILE *infile = fopen(infilename, "rb");
    gzFile outfile = gzopen(outfilename, "wb");
    if (!infile || !outfile)
    {
        return -1;
    } 
    while((num_read = fread(inbuffer, 1, sizeof(inbuffer), infile)) > 0) //读文件数据
    {
        total_read += num_read;
        gzwrite(outfile, inbuffer, num_read); //写到压缩文件中
        memset(inbuffer,0,128); //清空内存
    }
    fclose(infile); //关闭文件
    gzclose(outfile); //关闭压缩文件
    printf("原文件大小: %ld bytes\n 压缩后的文件大小: %ld bytes\n 压缩率 %4.2f%%\n",total_read, file_size(outfilename),(1.0-
file_size(outfilename)*1.0/total_read)*100.0);
    return 0;
}

int main(int argc, char **argv)
{
    compress_one_file(argv[1],argv[2]); //压缩文件 argv[1]是待压缩文件名,grgv[2]是压缩文件名
    //decompress_one_file(argv[1],argv[2]); //解压文件 argv[1]是压缩文件名,grgv[2]是解压后的文件名
    return 0;
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九月丫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值