使用 zlib 压缩解压文件
gzip 格式支持直接通过 gzip 命令解压或压缩
内存方式
缺点显而易见,需要很大的内存;不支持 gzip 格式文件
void read_file(const char *filename, uint8_t **buffer, size_t *size) {
FILE *in = fopen(filename, "rb");
fseek(in, 0, SEEK_END);
*size = ftell(in);
fseek(in, 0, SEEK_SET);
*buffer = malloc(*size);
size_t read = fread(*buffer, 1, *size, in);
*size = read;
fclose(in);
}
void compress_file(const char *filename_in, const char *filename_out) {
uint8_t *buffer_in;
size_t size;
read_file(filename_in, &buffer_in, &size);
FILE *out = fopen(filename_out, "wb");
size_t buffer_size = 10240;
if (buffer_size < size) {
buffer_size = size;
}
uint8_t buffer_out[buffer_size];
int ret = compress(buffer_out, &buffer_size, buffer_in, size);
fwrite(buffer_out, 1, buffer_size, out);
fclose(out);
}
void decompress_file(const char *filename_in, const char *filename_out) {
uint8_t *buffer_in;
size_t size;
read_file(filename_in, &buffer_in, &size);
FILE *out = fopen(filename_out, "wb");
size_t buffer_size = 10240;
if (buffer_size < size) {
buffer_size = size;
}
uint8_t buffer_out[buffer_size];
int ret = uncompress(buffer_out, &buffer_size, buffer_in, size);
fwrite(buffer_out, 1, buffer_size, out);
fclose(out);
}
文件流方式
必须通过文件,仅支持 gzip 格式
void compress_file(const char *filename_in, const char *filename_out) {
FILE *in = fopen(filename_in, "rb");
gzFile out = gzopen(filename_out, "wb");
uint32_t buffer_len = 10240;
uint8_t buffer[buffer_len];
while (1) {
size_t read = fread(buffer, 1, buffer_len, in);
if (read == 0) {
break;
}
gzwrite(out, buffer, read);
}
fclose(in);
gzclose(out);
}
void decompress_file(const char *filename_in, const char *filename_out) {
gzFile in = gzopen(filename_in, "rb");
FILE *out = fopen(filename_out, "wb");
uint32_t buffer_len = 10240;
uint8_t buffer[buffer_len];
while (1) {
size_t read = gzread(in, buffer, buffer_len);
if (read == 0) {
break;
}
fwrite(buffer, 1, read, out);
}
gzclose(in);
fclose(out);
}
内存流方式
代码更复杂,但是可配置性强,支持 zlib、gzip、deflate 三种格式
deflateInit2 参数说明
level
- 一般写默认 Z_DEFAULT_COMPRESSION
- 0表示不压缩
- 1 到 9,数字越大压缩率越高,同时也会占用更多资源
method
- 目前仅支持 Z_DEFLATED,其定义值是 8
windowBits
- 默认值:15
- -9 到 -15 表示纯 deflate 流
- 9 到 15 表示是 zlib 格式
- 大于 16 表示 gzip 格式,滑动窗口大小等于入参 -16
memLevel
- 目前默认都是填 8
strategy
- 一般填 Z_DEFAULT_STRATEGY
示例代码
void compress_file(const char *filename_in, const char *filename_out) {
FILE *in = fopen(filename_in, "rb");
FILE *out = fopen(filename_out, "wb");
const uint32_t buffer_size = 10240;
uint8_t buffer_in[buffer_size];
uint8_t buffer_out[buffer_size];
z_stream stream;
memset(&stream, 0, sizeof(stream));
// deflateInit(&stream, Z_DEFAULT_COMPRESSION);
// 滑动窗口,默认是15;-9到-15表示纯deflate流;9到15表示是zlib格式;大于16表示gzip格式,滑动窗口大小等于入参-16
// memLevel 一般填8
int ret = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
while (1) {
size_t read = fread(buffer_in, 1, 10240, in);
if (read == 0) {
break;
}
stream.next_in = buffer_in;
stream.avail_in = read;
do {
stream.next_out = buffer_out;
stream.avail_out = buffer_size;
ret = deflate(&stream, feof(in) ? Z_FINISH : Z_NO_FLUSH);
fwrite(buffer_out, 1, buffer_size - stream.avail_out, out);
} while (stream.avail_out == 0);
}
deflateEnd(&stream);
fclose(in);
fclose(out);
}
void decompress_file(const char *filename_in, const char *filename_out) {
FILE *in = fopen(filename_in, "rb");
FILE *out = fopen(filename_out, "wb");
const uint32_t buffer_size = 10240;
uint8_t buffer_in[buffer_size];
uint8_t buffer_out[buffer_size];
z_stream stream;
memset(&stream, 0, sizeof(stream));
int ret = inflateInit2(&stream, 15 + 16);
while (1) {
size_t read = fread(buffer_in, 1, 10240, in);
if (read == 0) {
break;
}
stream.next_in = buffer_in;
stream.avail_in = read;
do {
stream.next_out = buffer_out;
stream.avail_out = buffer_size;
ret = inflate(&stream, feof(in) ? Z_FINISH : Z_NO_FLUSH);
fwrite(buffer_out, 1, buffer_size - stream.avail_out, out);
} while (stream.avail_out == 0);
}
deflateEnd(&stream);
fclose(in);
fclose(out);
}
由于个人水平有限,文中若有不合理或不正确的地方欢迎指出改正