库的安装及使用
安装库,注意其中名称中是 1g 不是 lg。
sudo apt install zlib1g-dev
代码中需要引入头文件
#include <zlib.h>
编译时需要指定库 -lz
gcc zlib_test.c -lz
程序示例
本程序基于官网源程序zpipe.c的修改而来。
#include <zlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#define CHUNK 8192
int decompress_file(char *in_filename, char *out_filename)
{
z_stream stream;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
int fdin, fdout;
int have;
int ret, flush;
fdin = open(in_filename, O_RDONLY);
if (fdin < 0) {
perror(in_filename);
return Z_ERRNO;
}
fdout = open(out_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fdout < 0) {
perror(out_filename);
ret = Z_ERRNO;
goto close_in;
}
memset(&stream, 0, sizeof(stream));
ret = inflateInit(&stream);
if (ret != Z_OK)
goto close_out;
do {
stream.avail_in = read(fdin, in, CHUNK);
if (stream.avail_in < 0) {
ret = Z_ERRNO;
goto end_inflate;
}
if (stream.avail_in == 0)
break;
stream.next_in = in;
do {
stream.avail_out = CHUNK;
stream.next_out = out;
ret = inflate(&stream, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR);
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
case Z_MEM_ERROR:
goto end_inflate;
}
have = CHUNK - stream.avail_out;
if (write(fdout, out, have) != have) {
ret = Z_ERRNO;
goto end_inflate;
}
} while(stream.avail_out == 0);
} while(ret != Z_STREAM_END);
ret = (ret == Z_STREAM_END) ? Z_OK : Z_DATA_ERROR;
end_inflate:
(void) inflateEnd(&stream);
close_out:
close(fdout);
close_in:
close(fdin);
return ret;
}
int compress_file(char *in_filename, char *out_filename)
{
z_stream stream;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
int fdin, fdout;
int have;
int ret, flush;
fdin = open(in_filename, O_RDONLY);
if (fdin < 0) {
perror(in_filename);
return Z_ERRNO;
}
fdout = open(out_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fdout < 0) {
perror(out_filename);
ret = Z_ERRNO;
goto close_in;
}
memset(&stream, 0, sizeof(stream));
ret = deflateInit(&stream, Z_BEST_COMPRESSION);
if (ret != Z_OK)
goto close_out;
do {
stream.avail_in = read(fdin, in, CHUNK);
if (stream.avail_in < 0) {
ret = Z_ERRNO;
goto end_deflate;
}
flush = stream.avail_in ? Z_NO_FLUSH : Z_FINISH;
stream.next_in = in;
do {
stream.avail_out = CHUNK;
stream.next_out = out;
ret = deflate(&stream, flush);
assert(ret != Z_STREAM_ERROR);
have = CHUNK - stream.avail_out;
if (write(fdout, out, have) != have) {
ret = Z_ERRNO;
goto end_deflate;
}
} while (stream.avail_out == 0);
assert(stream.avail_in == 0);
} while(flush != Z_FINISH);
ret = Z_OK;
end_deflate:
(void) deflateEnd(&stream);
close_out:
close(fdout);
close_in:
close(fdin);
return ret;
}
/* report a zlib or i/o error */
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}
int main(int argc, char **argv)
{
int ret;
if (argc == 3) {
ret = compress_file(argv[1], argv[2]);
if (ret != Z_OK)
zerr(ret);
return ret;
}
else if (argc == 4 && strcmp(argv[1], "-d") == 0) {
ret = decompress_file(argv[2], argv[3]);
if (ret != Z_OK)
zerr(ret);
return ret;
}
else {
fputs("zpipe usage: zpipe [-d] source dest\n", stderr);
return 1;
}
}
结果对比
将原文件压缩,然后再解压缩,对比新文件其 sha256 是否一致。
shasum -a 256 file_name
本程序结果一致。