zlib-Deflate压缩算法
写在前边
最近在做一些关于网络优化的一些事情,涉及到对纯数据(Data、字符串、Json等)进行压缩,用到了Deflate
压缩算法,这里就简单说一下如何用OC实现 Deflate
先看代码 (后面会给出详细解析)
Deflate.h
//
// Deflate.h
// CompressionTest#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface Deflate : NSObject+ (NSData *)compress: (NSData *)data;
+ (NSData *)decompress: (NSData *)data;
@endNS_ASSUME_NONNULL_END
Deflate.m
//
// Deflate.m
// CompressionTest#import "Deflate.h"#include <zlib.h>#define CHUNK 16384@implementation Deflate/**Deflate 压缩@param data 需要压缩的数据@return 返回压缩数据*/
+ (NSData *)compress:(NSData *)data {if ([data length] == 0) return data;// 初始化 z_streamz_stream stream;stream.zalloc = Z_NULL;stream.zfree = Z_NULL;stream.opaque = Z_NULL;stream.total_out = 0;stream.next_in = (Bytef *)[data bytes];stream.avail_in = (int)[data length];// Compresssion Levels:// Z_NO_COMPRESSION// Z_BEST_SPEED// Z_BEST_COMPRESSION// Z_DEFAULT_COMPRESSIONif (deflateInit2(&stream,Z_DEFAULT_COMPRESSION,Z_DEFLATED,-15,MAX_MEM_LEVEL,Z_DEFAULT_STRATEGY) != Z_OK) return nil;NSMutableData * compressed = [NSMutableData dataWithLength: CHUNK];do {if (stream.total_out >= [compressed length])// 追加长度[compressed increaseLengthBy:CHUNK];stream.next_out = [compressed mutableBytes] + stream.total_out;stream.avail_out = (uint)[compressed length] - (uint)stream.total_out;deflate(&stream, Z_FINISH);} while (stream.avail_out == 0);deflateEnd(&stream);[compressed setLength: stream.total_out];return [NSData dataWithData:compressed];
}/**Deflate 解压缩@param data 需要解压数据@return 已经解压的数据*/
+ (NSData *)decompress:(NSData *)data {if ([data length] == 0) return data;// 初始化 z_streamz_stream strm;strm.zalloc = Z_NULL;strm.zfree = Z_NULL;strm.opaque = Z_NULL;strm.total_out = 0;strm.next_in = (Bytef *)[data bytes];strm.avail_in = (int)[data length];unsigned full_length = (int)[data length];unsigned half_length = (int)[data length] / 2;NSMutableData * decompressed = [[NSMutableData alloc]initWithLength: full_length + half_length];BOOL done = false;int status;if (inflateInit2(&strm, -15) != Z_OK) return nil;while (!done) {if (strm.total_out >= [decompressed length])[decompressed increaseLengthBy: half_length];strm.next_out = [decompressed mutableBytes] + strm.total_out;strm.avail_out = (uint)[decompressed length] - (uint)strm.total_out;status = inflate(&strm, Z_SYNC_FLUSH);if (status == Z_STREAM_END)done = YES;else if (status != Z_OK)break;}if (inflateEnd(&strm) != Z_OK) return nil;if (done) {[decompressed setLength: strm.total_out];return [NSData dataWithData:decompressed];}return nil;
}@end
相关概念
deflate(RFC1951):一种压缩算法,使用LZ77和哈弗曼进行编码;
zlib(RFC1950):一种格式,是对deflate进行了简单的封装,他也是一个实现库(delphi
中有zlib
,zlibex
)
gzip(RFC1952):一种格式,也是对deflate进行的封装。
gzip = gzip头 + deflate编码的实际内容 + gzip尾
zlib = zlib头 + deflate编码的实际内容 + zlib尾
基础数据结构
z_stream
: 压缩算法,压缩程度以及输入输出buffer
和长度等都保存在这里,可以理解为压缩上下文。
常用的函数
deflateInit
: 参数比较少,里面的实现其实是调用的deflateInit2
deflateInit2
: 压缩初始化的基础函数,有很多参数,下面会重点介绍。
deflate
: 压缩函数。
deflateEnd
: 压缩完成以后,释放空间,但是注意,仅仅是释放deflateInit
中申请的空间,自己申请的空间还是需要自己释放。
inflateInit
: 解压初始化函数,内部调用的inflateInit2
。
inflateInit2
: 解压初始化的基础函数,后面重点介绍。
infalte
: 解压函数。
inflateEnd
: 同deflateEnd
作用类似。
compress
: 全部附加选项默认压缩,内部调用compress2。
compress2
: 带level的压缩方式。
uncompress
: 解压缩。
压缩函数介绍
deflateInit2 : 初始化函数
函数原型为 :
int ZEXPORT deflateInit2(z_streamp strm, int level, int method, int windowBits, int memLevel, intstrategy)
z_stream
:这个是压缩上下文,我们依照官方给的例子进行初始化
strm.zalloc = NULL;
strm.zfree = NULL;
strm.opaque = NULL;strm.next_in = 你的待压缩数据
strm.next_out = 压缩以后数据存储的buffer
strm.avail_in = 待压缩数据的长度
strm.avail_out = 压缩数据存储buffer的长度.
level
: 压缩的等级,目前有四个值
#define Z_NO_COMPRESSION 0 //不压缩
#define Z_BEST_SPEED 1 //速度优先,可以理解为最低限度的压缩.
#define Z_BEST_COMPRESSION 9 //压缩优先,但是速度会有些慢
#define Z_DEFAULT_COMPRESSION (-1) //默认选项,compress里面用的就是这个选项
/* compression levels */
method
: 值只有一个,当前唯一的defalte
压缩方法,用于以后扩展
#define Z_DEFLATED 8
/* The deflate compression method (the only one supported in this version) */
windowBits
: 窗口比特数
* -(15 ~ 8) : 纯deflate压缩
* +(15 ~ 8) : 带zlib头和尾
* > 16 : 带gzip头和尾
memLevel
: 目前只有一个选项,MAX_MEM_LEVEL
,无非是运行过程中对内存使用的限制.
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
strategy
:用于调整压缩算法,直接给默认就行Z_DEFAULT_STRATEGY
.
#define Z_FILTERED 1 //用于由filter(或者称为predictor)生成的数据
#define Z_HUFFMAN_ONLY 2 //用于强制哈夫曼编码(不做字符匹配)
#define Z_RLE 3 //限制匹配长度为1
#define Z_FIXED 4 //阻止使用动态哈夫曼编码,从而允许获得更简单的解码
#define Z_DEFAULT_STRATEGY 0 //用于普通数据
/* compression strategy; see deflateInit2() below for details */
Z_FILTERED,用于由filter(或者称为predictor)生成的数据.过滤的数据包含很多小的随机数据。这种情况下,压缩算法能够获得更好的压缩效果。该选项可以强制更多的哈夫曼编码和更少的字符匹配。有时候可以作为Z_DEFAULT_STRATEGY和Z_HUFFMAN_ONLY的折衷。
Z_FIXED,阻止使用动态哈夫曼编码,从而允许获得更简单的解码。
strategy参数只影响压缩比,而不会影响到压缩输出的正确性,因此没有正确的设置也不要紧。
deflate 压缩函数
函数原型 :
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
解压函数介绍
inflateInit2 初始化
原型函数
inflateInit2(z_streampstrm, int windowBits)
strm
: 和deflate
一样,初始化三个回调以后即可,有的参考文档说还需要初始化第四个选项,具体记不清哪个了,不过我试过以后发现貌似不用。
windownBits
: 含义和deflateInit2
一样,而且一定要对应起来.
inflate 解压
函数原型
ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
z_streamp
: 四个参数.
strm.next_in = 你的待解压数据
strm.next_out = 解压以后数据存储的buffer
strm.avail_in = 待解压数据的长度
strm.avail_out = 解压数据存储buffer的长度.
flush
: 和deflate
一样,如果是Z_NO_FLUSH
说明还有数据没有解压,如果是Z_FINISH
说明这是最后一包待解压数据.
inflateEnd
: 释放上面两步骤里面申请的资源.
uncompress
:
函数原型 :
ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,const Bytef *source, uLong sourceLen));
dest
: 解压以后的数据存在这里
destLen
: dest 大小
source
: 待解压数据buffer
sourceLen
: 待解压数据长度
其实这个函数就是简单封装了inflateInit
, inflate
, inflateEnd
.同样,这个函数只适合单独解压场景,不适合需要多次传入的场景.
相关链接:
https://yq.aliyun.com/articles/40985
https://github.com/tsolomko/SWCompression
zlib-Deflate压缩算法相关推荐
- Gzip Zlib PNG 压缩算法【转】
gzip,zlib,以及图形格式png,使用的是同一个压缩算法deflate.我们通过对gzip源码的分析来对deflate压缩算法做一个详细的说明.我阅读的gzip版本为 gzip-1.2.4.我们 ...
- 文章分享:Gzip 格式和 DEFLATE 压缩算法详解
Introduction 引言: 当键入 tar -zcf src.tar.gz src 时,就可以将 src 下的所有文件打包成一个 tar.gz 格式的压缩包.这里的 "tar" ...
- GZip、Deflate压缩算法对应的C#压缩解压函数
GZip解压函数 View Code GZip压缩函数 View Code 1 /// <summary> 2 /// GZip压缩函数 3 /// </summary> 4 ...
- java restfulapi 返回文件base64_Java反序列化:一次构造后Ysoserial Payload
前言 在一次应用安全测试中发现了一个的Java反序列化漏洞,该漏洞最终导致未经身份验证的远程代码执行.经过实践,发现利用此漏洞并不像之前使用Ysoserial生成默认payload那样简单. 所以在本 ...
- (二)Java网络编程之爆肝HTTP、HTTPS、TLS协议及对称与非对称加密原理!
引言 在上篇文章中,已经讲明了当下计算机网络的基础知识,其中对网络体系结构.分层模型.TCP/IP协议簇.....等多方面内容进行了阐述,而在本章会分析到网络知识中另外两个大名鼎鼎的协议:HTTP/H ...
- Zlib压缩算法:LZ77、LZ78、霍夫曼编码、滑动窗口、Rabin-Karp算法、哈希链、I/O缓冲区
Table of Contents 1.简介 1.1 什么是zlib 2.压缩算法 2.1 放气 2.2 LZ77 2.2.1 滑动窗口 2.2.2 长距离对 2.3 霍夫曼编码 3. zlib的实现 ...
- 字符编码、Unicode原理、数据流压缩Zlib与Miniz的实现
字符集和字符编码的区别和联系 字符集:多个字符的集合.例如 GB2312 是中国国家标准的简体中文字符集,GB2312 收录简化汉字(6763 个)及一般符号.序号.数字.拉丁字母.日文假名.希腊字母 ...
- zlib解压 被压缩的PDF(关键字FlateDecode)
PDF被压缩了,但从网上看这个压缩算法就是zlib的压缩算法,下面的乱码就是压缩导致的乱码,现在需要把这些乱码复原 %PDF-1.7 %溷弦 4 0 obj <</Length 3 0 R ...
- 数据流压缩之应用篇zlib库
关于数据流压缩的原理,lz77以及huffman编码可以参考上一篇: https://blog.csdn.net/sesiria/article/details/116835301 本篇将包含以下内容 ...
- 数据流压缩原理实现(huffman编码,LZ77压缩算法)
1. 压缩原理deflate算法 a) LZ77 算法原理 b) Huffman算法原理 c) Huffman算法测试实例 2. 关于zlib库的实际应用以及gzip格式分析查看下一篇 一.数据压缩 ...
最新文章
- RabbitMQ Node.js 示例
- spring源码分析之spring-jdbc模块详解
- 开关电源雷击浪涌整改_大佬多年经验总结,开关电源EMI整改策略
- 同期及上期数据对比处理示例.sql
- Androida规划nt打包
- excel导入linux乱码怎么解决方法,,请大家都来看下,Excel导入有乱码?原因出在哪里?应该怎么解决?...
- 安装java 并配置环境变量_安装Java JDK并配置环境变量
- 2017.10.23学习知识总结回顾及编写新网页
- Phonetics: Lecture Three 语音 第三课 Teacher:Patrick
- Linux系统知识汇总
- electron入门笔记(三)- 引入bootstrap
- 前端项目emoji表情包的使用
- 月薪50K的测试工程师,要求原来是这样!
- 京东股权众筹投后总结和反思
- iOS视频——视频文件、播放视频
- 写给通信年轻人的27个忠告
- NLS(National Language Support)
- SQL sever 数据库数据类型
- Python 列表、元素、字典
- stlinkv2红灯闪烁_ST-LINK V2 DIY笔记(一)
热门文章
- 服务器版本与操作系统兼容性,服务器跟操作系统兼容性
- 微信小程序使用高德API获取位置信息
- multisim仿真 电流控制的电压源电路连接方法
- 大学计算机应用实验项目综合报告书,大学计算机应用基础实验报告册_2010版_.doc...
- 这样“断舍离”,你会活得更高级
- python图片转化为素描图
- 一般大学生的计算机水平,现代大学生应该具备怎样的计算机水平?
- 图像增强-点处理方法总结
- 如何学习python+人工智能
- 对方向导数和梯度的理解