likes
comments
collection
share

压缩和归档库-Zlib介绍

作者站长头像
站长
· 阅读数 61

1.简介

zlib是一个广泛使用的压缩库,它提供了一系列的函数用于压缩和解压缩数据。zlib使用DEFLATE压缩算法,这是一种无损压缩算法,通常与gzip和zip文件格式一起使用。zlib库本身支持的压缩文件格式是它自己的专有格式,通常用于数据流的无损压缩。这种格式不是一种标准的文件格式,而是一种内存中的压缩数据表示,常用于网络传输、数据库和应用程序内部的数据压缩。

zlib库通常用于:

  • 压缩网络传输数据以减少带宽使用。
  • 压缩存储数据以减少所需的存储空间。

2.接口介绍

压缩数据

int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);

参数说明:

  • dest:指向用于存储压缩数据的缓冲区的指针。
  • destLen:一个指向uLongf类型变量的指针,该变量在调用函数前应包含dest缓冲区的大小,在函数返回时将包含压缩数据的实际长度。
  • source:指向要压缩的数据的指针。
  • sourceLen:要压缩的数据的长度。

返回值:

  • Z_OK:压缩成功。
  • Z_MEM_ERROR:内存不足,无法进行压缩。
  • Z_BUF_ERROR:提供的dest缓冲区太小,无法存储压缩数据。

使用compress函数时,你需要确保dest缓冲区足够大以存储压缩后的数据。通常,压缩后的数据长度不会超过源数据长度的0.001倍加上12字节。因此,你可以按照以下方式分配dest缓冲区的大小:

uLongf destLen = sourceLen * 1.001 + 12;
Bytef *dest = (Bytef *)malloc(destLen);

解压缩数据

int uncompress(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen);
  • dest:指向存放解压缩后数据的缓冲区的指针。
  • destLen:传入时为解压缩缓冲区的大小,传出时为实际解压缩后数据的大小。
  • source:指向待解压缩数据的缓冲区的指针。
  • sourceLen:待解压缩数据的大小。

返回值:

  • Z_OK:解压缩成功。
  • Z_MEM_ERROR:内存分配失败。
  • Z_BUF_ERROR:解压缩输出缓冲区不足。
  • Z_DATA_ERROR:输入数据错误或损坏。

3.环境搭建

下载地址:github.com/madler/zlib… 压缩和归档库-Zlib介绍 解压后使用cmake编译: 压缩和归档库-Zlib介绍 生成库: 压缩和归档库-Zlib介绍 拷贝生成的库文件,和zconf.h、zlib.h文件到我们的工程目录下。 压缩和归档库-Zlib介绍 配置visual studio环境。 具体看Jsoncpp介绍

4.示例

示例1:压缩/解压缩数据:。

#include <iostream>
#include <zlib.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <vector>

#define CHUNK 16384

using namespace std;


int main()
{
	const char* input = "This is a string that we want to compress.This is a string that we want to compress";
	unsigned long sourceLen = strlen(input);
	unsigned char* compressed = NULL;
	unsigned long compressedLen = sourceLen * 1.001 + 12;

	compressed = (unsigned char*)realloc(compressed,compressedLen);
	if (compressed == NULL)
	{
		printf("Failed to allocate memory for compressed data.\n");
		return -1;
	}
	
	// 压缩数据
	int ret = compress(compressed, &compressedLen, (const Bytef*)input, sourceLen);
	if (Z_OK == ret)
	{
		printf("compress success!!!\n");
		printf("Original size: %lu\n", sourceLen);
		printf("Compressed size: %lu\n", compressedLen);
	}

	unsigned char* decompressed = NULL;
	unsigned long decompressedLen = sourceLen;

	decompressed = (unsigned char*)realloc(decompressed,decompressedLen);
	// 解压缩数据
	uncompress(decompressed, &decompressedLen, compressed, compressedLen);

	printf("Decompressed string: %s\n", decompressed);

	// 释放内存
	free(compressed);

	return 0;
}

运行截图: 压缩和归档库-Zlib介绍 示例2:压缩/解压缩文件

#include <iostream>
#include <zlib.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>
#include <vector>

using namespace std;

bool compressFile(const std::string& sourceFilename, const std::string& compressedFilename) 
{
	std::ifstream source(sourceFilename, std::ios_base::binary);
	std::ofstream dest(compressedFilename, std::ios_base::binary);

	if (!source || !dest)
	{
		std::cerr << "Could not open source or destination file." << std::endl;
		return false;
	}

	z_stream zs;
	memset(&zs, 0, sizeof(zs));

	if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK) 
	{
		std::cerr << "deflateInit failed while compressing." << std::endl;
		return false;
	}

	// 压缩缓冲区
	const size_t bufSize = 128 * 1024;
	std::vector<char> inBuffer(bufSize);
	std::vector<char> outBuffer(bufSize);

	int deflateStatus;
	do 
	{
		// 读取源文件内容到缓冲区
		source.read(inBuffer.data(), inBuffer.size());
		zs.next_in = reinterpret_cast<Bytef*>(inBuffer.data());
		zs.avail_in = source.gcount();	//实际读取字节数

		do 
		{
			zs.next_out = reinterpret_cast<Bytef*>(outBuffer.data());
			zs.avail_out = outBuffer.size();	//next_out剩余可用空间

			deflateStatus = deflate(&zs, source.eof() ? Z_FINISH : Z_NO_FLUSH);

			if (deflateStatus == Z_STREAM_ERROR)
			{
				std::cerr << "Deflate failed during compression." << std::endl;
				deflateEnd(&zs);
				return false;
			}

			// 写入压缩数据到目标文件
			int have = outBuffer.size() - zs.avail_out;
			dest.write(outBuffer.data(), have);
		} while (zs.avail_out == 0);

	} while (deflateStatus != Z_STREAM_END);

	deflateEnd(&zs);
	return true;
}

bool decompressFile(const std::string& compressedFilename, const std::string& destFilename) 
{
	std::ifstream source(compressedFilename, std::ios_base::binary);
	std::ofstream dest(destFilename, std::ios_base::binary);

	if (!source || !dest)
	{
		std::cerr << "Could not open source or destination file." << std::endl;
		return false;
	}

	z_stream zs;
	memset(&zs, 0, sizeof(zs));

	if (inflateInit(&zs) != Z_OK)
	{
		std::cerr << "inflateInit failed while decompressing." << std::endl;
		return false;
	}

	const size_t bufSize = 128 * 1024;
	std::vector<char> inBuffer(bufSize);
	std::vector<char> outBuffer(bufSize);

	int inflateStatus;
	do 
	{
		source.read(inBuffer.data(), inBuffer.size());
		zs.next_in = reinterpret_cast<Bytef*>(inBuffer.data());
		zs.avail_in = source.gcount();

		do
		{
			zs.next_out = reinterpret_cast<Bytef*>(outBuffer.data());
			zs.avail_out = outBuffer.size();

			inflateStatus = inflate(&zs, Z_NO_FLUSH);

			if (inflateStatus == Z_NEED_DICT || inflateStatus == Z_DATA_ERROR || inflateStatus == Z_MEM_ERROR)
			{
				std::cerr << "Inflate failed during decompression." << std::endl;
				inflateEnd(&zs);
				return false;
			}

			int have = outBuffer.size() - zs.avail_out;
			dest.write(outBuffer.data(), have);
		} while (zs.avail_out == 0);
	} while (inflateStatus != Z_STREAM_END);

	inflateEnd(&zs);
	return true;
}

int main()
{
	bool ret = compressFile("E:/2.mp4", "E:/2.zlib");
	//bool ret = decompressFile("E:/2.zlib", "E:/3.mp4");
	return 0;
}

5.更多参考

libVLC 专栏介绍-CSDN博客

Qt+FFmpeg+opengl从零制作视频播放器-1.项目介绍_qt opengl视频播放器-CSDN博客

QCharts -1.概述-CSDN博客

JSON++介绍

转载自:https://juejin.cn/post/7366899841454063626
评论
请登录