网上有很多针对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
参考内容链接: