zlib的简单使用

zlib的简单使用

1.介绍

zlib 是一个广泛使用的数据压缩库,它提供了内存中的压缩和解压缩功能,并能够检查解压数据的完整性。zlib 支持读写 gzip (.gz) 格式的文件,并且默认使用 deflate 算法进行数据压缩,这是一种增强的 Huffman 编码算法。

2.安装

zlib Home Site

3.一次性读入内存解压缩compress和uncompress

#include

#include "zlib.h"

int main()

{

/* 原始数据 */

unsigned char strSrc[] = "hello world!中文测试 yes";

unsigned char buf[1024] = {0};

unsigned char strDst[1024] = {0};

unsigned long srcLen = sizeof(strSrc);

unsigned long bufLen = sizeof(buf);

unsigned long dstLen = sizeof(strDst);

printf("Src string:%s\nLength:%ld\n", strSrc, srcLen);

/* 压缩 */

compress(buf, &bufLen, strSrc, srcLen);

printf("After Compressed Length:%ld\n", bufLen);

/* 解压缩 */

uncompress(strDst, &dstLen, buf, bufLen);

printf("After UnCompressed Length:%ld\n",dstLen);

printf("UnCompressed String:%s\n",strDst);

return 0;

}

示例解压缩一段字符串,对文件使用这两个函数时,也是一次性在内存中进行解压缩,适用于小文件,大文件应采用分块流式解压缩。

4.分块解压缩(流式)

官方示例 zlib 使用示例

#include

#include

#include

#include

#include

#include

bool compress_data(const std::string& input_file_name, const std::string& output_file_name){

std::ifstream input_file(input_file_name, std::ios::binary);

if (!input_file) {

spdlog::error("Failed to open input file: {}", input_file_name);

return false;

}

std::ofstream output_file(output_file_name, std::ios::binary);

if (!output_file) {

spdlog::error("Failed to open output file: {}", output_file_name);

return false;

}

// 设置压缩参数zstream

z_stream strm;

strm.zalloc = Z_NULL;

strm.zfree = Z_NULL;

strm.opaque = Z_NULL;

strm.avail_in = 0;

strm.next_in = Z_NULL;

// 初始化压缩流

if(deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK){

spdlog::error("Failed to initialize deflate stream");

return false;

}

// 读取输入文件并压缩数据

const int buffer_size = 16 * 1024;

std::vector buffer(buffer_size);

do {

input_file.read(buffer.data(), buffer_size);

strm.avail_in = static_cast(input_file.gcount()); //读到的字节数

strm.next_in = reinterpret_cast(buffer.data()); //输入缓冲区

do {

std::vector output_buffer(buffer_size);

strm.avail_out = buffer_size;

strm.next_out = reinterpret_cast(output_buffer.data());

// 压缩数据

int result = deflate(&strm, input_file.eof() ? Z_FINISH : Z_NO_FLUSH); //是否到文件末尾

if (result == Z_STREAM_ERROR){

spdlog::error("Error during compression: {}", strm.msg);

deflateEnd(&strm);

return false;

}

//加密

// 写入压缩后的数据到输出文件 发送到网络

std::streamsize compressed_size = buffer_size - strm.avail_out;

output_file.write(output_buffer.data(), compressed_size);

} while(strm.avail_out == 0);

} while(!input_file.eof());

// 压缩结束

deflateEnd(&strm);

input_file.close();

output_file.close();

return true;

}

bool decompress_data(const std::string& input_file_name, const std::string& output_file_name){

std::ifstream input_file(input_file_name, std::ios::binary);

if (!input_file) {

spdlog::error("Failed to open input file: {}", input_file_name);

return false;

}

std::ofstream output_file(output_file_name, std::ios::binary);

if(!output_file){

spdlog::error("faild to open output file: {}", output_file_name);

}

// 设置解压缩参数

z_stream strm;

strm.zalloc = Z_NULL;

strm.zfree = Z_NULL;

strm.opaque = Z_NULL;

strm.avail_in = 0;

strm.next_in = Z_NULL;

//初始化解压缩流

if(inflateInit(&strm) != Z_OK){

spdlog::error("Failed to initialize inflate stream");

return false;

}

const int buffer_size = 16 * 1024;

std::vector buffer(buffer_size);

do {

input_file.read(buffer.data(), buffer_size);

//格式转换

strm.avail_in = static_cast(input_file.gcount());

strm.next_in = reinterpret_cast(buffer.data());

do {

std::vector output_file_buffer(buffer_size);

strm.avail_out = buffer_size;

strm.next_out = reinterpret_cast(output_file_buffer.data());

//解压缩数据

int result = inflate(&strm, input_file.eof() ? Z_FINISH : Z_NO_FLUSH);

if (result == Z_STREAM_ERROR){

spdlog::error("Error during decompression: {}", strm.msg);

inflateEnd(&strm);

return false;

}

//写入解压缩后的数据到输出文件

std::streamsize uncompressed_size = buffer_size - strm.avail_out;

output_file.write(output_file_buffer.data(), uncompressed_size);

} while(strm.avail_out == 0);

} while(!input_file.eof());

//解压缩结束

inflateEnd(&strm);

input_file.close();

output_file.close();

return true;

}

int main(){

std::string input_file_name = "/root/test1/OIP-C.jpg";

std::string compressed_file_name = "/root/test1/compressed.bin";

std::string decompressed_file_name = "/root/test1/decompressed.jpg";

if(compress_data(input_file_name, compressed_file_name)){

spdlog::info("Data compressed successfully.");

}

else {

spdlog::error("Failed to compress data.");

return 1;

}

if(decompress_data(compressed_file_name, decompressed_file_name)){

spdlog::info("Data decompressed successfully.");

}

else {

spdlog::error("Failed to decompress data.");

return 1;

}

return 0;

}

5.压缩的流程

初始化结构体z_stream

初始化一个 z_stream 结构体 strm,并将一些字段设置为默认值:

zalloc 和 zfree 设置为 Z_NULL,表示使用默认的内存分配和释放函数。

opaque 设置为 Z_NULL,表示没有附加的数据。

avail_in 设置为 0,表示输入缓冲区中可用的数据长度为 0。

next_in 设置为 Z_NULL,表示输入缓冲区的指针为 NULL。

初始化压缩流(deflateInit 函数)

int deflateInit(z_stream strm, int level);*

strm:指向 z_stream 结构体的指针。

level:压缩级别,范围从 Z_NO_COMPRESSION 到 Z_BEST_COMPRESSION。

使用 deflateInit 函数初始化压缩流,并检查初始化是否成功。如果初始化失败,则记录错误信息并返回 false。

开始压缩 (deflate函数)

int deflate(z_stream strm, int flush);*

strm:指向 z_stream 结构体的指针。

flush:刷新标志,可以是 Z_NO_FLUSH、Z_PARTIAL_FLUSH、Z_SYNC_FLUSH、Z_FULL_FLUSH 或 Z_FINISH。

外部的 do-while 循环会一直执行,直到输入文件 input_file 读取完毕。

内部的 do-while 循环用于处理每次压缩操作。

初始化一个输出缓冲区 output_buffer,大小与输入缓冲区相同。

设置 avail_out 和 next_out 来指向输出缓冲区。

使用 deflate 函数进行压缩操作。如果当前是文件末尾,则传入 Z_FINISH,否则传入 Z_NO_FLUSH。

检查压缩结果是否为 Z_STREAM_ERROR,如果是则记录错误信息并结束压缩流。

计算实际压缩的字节数 compressed_size,并将其写入输出文件 output_file

结束释放资源(deflateEnd)

6.解压流程

解压也是类似的操作,不在赘述。稍加修改就能应用于网络传输,各种文件解压缩等。

🎭 相关推荐 🎭

撮是什么意思撮的解释 撮怎么读
365下载bet

撮是什么意思撮的解释 撮怎么读

📅 01-11 👀 4323
新中源瓷砖好还是马可波罗瓷砖好?谁能够指点一下?
如何找到ps滤镜所在的文件夹?
约彩365彩票app下载安装

如何找到ps滤镜所在的文件夹?

📅 10-13 👀 6268