zlib压缩一个文件为gzip格式

时间:2021-09-22 19:57:13

网上有很多针对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