zlib压缩一个文件为gzip格式

网上有很多针对zlib的总结,但是很零散,自己经过总结,实现了用zlib压缩一个文件为gzip格式,似的可以直接使用winr工具解压。

具体方法是使用zlib的deflate系列函数,将buffer压缩为gzip格式,deflateInit2的参数注意使用MAX_WBITS+16,这样压缩后可以带gzip的头、尾信息。

然后将压缩后的内容直接写入到目标文件,保存为.gz, 使用WinR就可以直接解压了。

demo程序如下(deflate_gzip.c):

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <zlib.h>
  4  
  5 /*******************************************************************************
  6 * Compress gzip data
  7 * @parm[data] data buffer to be compressed
  8 * @parm[dlen] data buffer length
  9 * @parm[zdata] data buffer to save the compressed datas
 10 * @parm[zdlen] compressed data buffer length
 11 * return: 0 - OK; -1 - FAIL 
 12 *******************************************************************************/ 
 13 int gzcompress(Bytef *data, uLong dlen, Bytef *zdata, uLong *zdlen)
 14 {
 15     int err = 0;
 16     z_stream c_stream;
 17     
 18     printf("%s: data=%p, dlen=%lu, zdata=%p, *zdlen=%lu\n",
 19         __func__, data, dlen, zdata, *zdlen);
 20     
 21     if(data && dlen > 0) 
 22     {
 23         c_stream.zalloc = NULL;
 24         c_stream.zfree = NULL;
 25         c_stream.opaque = NULL;
 26         //use parm 'MAX_WBITS+16' so that gzip headers are contained
 27         if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
 28             MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) 
 29         {
 30             printf("%s: deflateinit2 failed!\n",__func__);
 31             return -1;
 32         }
 33         c_stream.next_in  = data;
 34         c_stream.avail_in  = dlen;
 35         c_stream.next_out = zdata;
 36         c_stream.avail_out  = *zdlen;
 37         while(c_stream.avail_in != 0 && c_stream.total_out < *zdlen)
 38         {
 39             if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) {
 40                 printf("%s: deflate failed!\n",__func__);
 41                 return -1;
 42             }
 43         }
 44         if(c_stream.avail_in != 0) {
 45             printf("%s: avail_in not zero!\n",__func__);
 46             return c_stream.avail_in;
 47         }
 48         for(;;) 
 49         {
 50             if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END)
 51                 break;
 52             if(err != Z_OK) {
 53                 printf("%s: deflate finish fail: %d\n",__func__, err);
 54                 return -1;
 55             }
 56         }
 57         if(deflateEnd(&c_stream) != Z_OK) {
 58             printf("%s: deflate end failed!\n",__func__);
 59             return -1;
 60         }
 61         *zdlen = c_stream.total_out;
 62         return 0;
 63     }
 64     return -1;
 65 }
 66 
 67 /*******************************************************************************
 68 * Compress a file into a gzip file
 69 * @parm[input_name] the file path to be compressed
 70 * @parm[output_name] output path of compressed gzip file
 71 * return: 0 - OK; -1 - FAIL 
 72 *******************************************************************************/ 
 73 int compress_file_to_gzip(char * input_name, char * output_name)
 74 {
 75     FILE *fp = NULL;
 76     uLong flen, clen;
 77     unsigned char * fbuf = NULL;
 78     unsigned char * cbuf = NULL;
 79     char def_output_name[PATH_MAX] = {0};    
 80 
 81     if((fp = fopen(input_name, "rb")) == NULL)
 82     {
 83         printf("%s: can not open %s!\n", __func__, input_name);
 84         return -1;
 85     }
 86     
 87     /*load file content to buffer*/
 88     fseek(fp, 0L, SEEK_END);
 89     flen = ftell(fp);
 90     fseek(fp, 0L, SEEK_SET);
 91     fbuf = (unsigned char *)malloc(flen * sizeof(unsigned char));
 92     if(NULL == fbuf){
 93         printf("%s: no enough memory!\n", __func__);
 94         goto __error;
 95     }
 96     fread(fbuf, sizeof(unsigned char), flen, fp);
 97     fclose(fp);
 98     fp = NULL;
 99     
100     /*compute compressBound*/
101     clen = compressBound(flen);
102     cbuf = (unsigned char *)malloc(clen * sizeof(unsigned char));
103     if(NULL == cbuf) {
104         printf("%s: no enough memory!\n", __func__);
105         goto __error;
106     }
107     
108     if(gzcompress(fbuf, flen, cbuf, &clen))
109     {
110         printf("%s: compress %s failed!\n", __func__, input_name);
111         goto __error;
112     }
113 
114     if(NULL == output_name) {
115         snprintf(def_output_name, sizeof(def_output_name),
116         "%s.gz", input_name);
117         output_name = def_output_name;
118     }
119     if((fp = fopen(output_name, "wb")) == NULL)
120     {
121         printf("%s: can not open %s!\n", __func__, output_name);
122         goto __error;
123     }
124     fwrite(cbuf, sizeof(unsigned char), clen, fp);
125     
126     fclose(fp);
127     free(fbuf);
128     free(cbuf);
129     return 0;
130 
131 __error:
132     if(fp) fclose(fp);
133     if(fbuf) free(fbuf);
134     if(cbuf) free(cbuf);
135     return -1;
136 }
137 
138 int main(int argc, char * argv[])
139 {
140     if(argc < 2) {
141         printf("too few args!\n");
142         return 0;
143     }
144 
145     if(argc < 3) {
146         return compress_file_to_gzip(argv[1],NULL);
147     }
148 
149     return compress_file_to_gzip(argv[1], argv[2]);
150 }

编译命令:

gcc -o zlibtest deflate_gzip.c.c -lz

如果编译连接的时候示找不到deflate等函数,则需要安装zlib库,ubuntu下:

sudo apt-get install zlib1g zlib1g-dev zlibc

参考内容链接:

http://www.oschina.net/code/snippet_65636_22542

http://blog.csdn.net/turingo/article/details/8178510

原文地址:https://www.cnblogs.com/yanghaizhou/p/5268692.html