lz4是目前综合来看效率最高的压缩算法,更加侧重压缩解压速度,压缩比并不是第一。在当前的安卓和苹果操作系统中,内存压缩技术就使用的是lz4算法,及时压缩手机内存以带来更多的内存空间。本质上是时间换空间。
lz4压缩算法其实很简单,举个压缩的栗子
其中两个括号内的便代表的是压缩时检测到的重复项,(5,4) 代表向前5个byte,匹配到的内容长度有4,即"bcde"是一个重复。当然也可以说"cde"是个重复项,但是根据算法实现的输入流扫描顺序,我们取到的是第一个匹配到的,并且长度最长的作为匹配。
压缩后的数据是下面的格式
其他情况也可能有连续的匹配:
Literals 指没有重复、首次出现的字节流,即不可压缩的部分
Match 指重复项,可以压缩的部分
Token 记录literal长度,match长度。作为解压时候memcpy的参数
可以想到,如果重复项越多或者越长,压缩率就会越高。上述例子中"bcde"在压缩后,用(5,4)表示,即从4个bytes压缩成了3个bytes来表示,其中offset 2bytes, match length 1byte,能节省1个byte。
大致流程,压缩过程以至少4个bytes为扫描窗口查找匹配,每次移动1byte进行扫描,遇到重复的就进行压缩。
由于offset用2bytes表示,只能查找到到2^16(64kb)距离的匹配,对于压缩4Kb的内核页,只需要用到12位。
扫描的步长1byte是可以调整的,即对应LZ4_compress_fast机制,步长变长可以提高压缩解压速度,减少压缩率。
我们来看下 apple的lz4实现
压缩理解了其实解压也很简单
根据解压前的数据流,取出token内的length,literals直接复制到输出,即memcpy(src,dst,length)
遇到match,在从前面已经拷贝的literals复制到后面即可
⑵ 算法解析:哈夫曼(huffman)压缩算法
本篇将介绍 哈夫曼压缩算法(Huffman compression)
众所周知,计算机存储数据时,实际上存储的是一堆0和1(二进制)。
如果我们存储一段字符:ABRACADABRA!
那么计算机会把它们逐一翻译成二进制,如A:01000001;B: 01000010; !: 00001010.
每个字符占8个bits, 这一整段字符则至少占12*8=96 bits。
但如果我们用一些特殊的值来代表这些字符,如:
图中,0代表A; 1111代表B;等等。此时,存储这段字符只需30bits,比96bits小多了,达到了压缩的目的。
我们需要这么一个表格来把原数据翻译成特别的、占空间较少的数据。同时,我们也可以用这个表格,把特别的数据还原成原数据。
首先,为了避免翻译歧义,这个表格需满足一个条件: 任何一个字符用的值都不能是其它字符的前缀 。
我们举个反例:A: 0; B: 01;这里,A的值是B的值的前缀。如果压缩后的数据为01xxxxxx,x为0或者1,那么这个数据应该翻译成A1xxxxxx, 还是Bxxxxxxx?这样就会造成歧义。
然后,不同的表格会有不同的压缩效果,如:
这个表格的压缩效果更好。
那么我们如何找到 最好的表格 呢?这个我们稍后再讲。
为了方便阅读,这个表格是可以写成一棵树的:
这棵树的节点左边是0,右边是1。任何含有字符的节点都没有非空子节点。(即上文提及的前缀问题。)
这棵树是在压缩的过程中建成的,这个表格是在树形成后建成的。用这个表格,我们可以很简单地把一段字符变成压缩后的数据,如:
原数据:ABRACADABRA!
表格如上图。
令压缩后的数据为S;
第一个字符是A,根据表格,A:11,故S=11;
第二个字符是B,根据表格,B:00,故S=1100;
第三个字符是R,根据表格,R:011,故S=1100011;
如此类推,读完所有字符为止。
压缩搞定了,那解压呢?很简单,跟着这棵树读就行了:
压缩后的数据S=11000111101011100110001111101
记住,读到1时,往右走,读到0时,往左走。
令解压后的字符串为D;
从根节点出发,第一个数是1,往右走:
第二个数是1,往右走:
读到有字符的节点,返回此字符,加到字符串D里。D:A;
返回根节点,继续读。
第三个数是0,往左走:
第四个数是0,往左走:
读到有字符的节点,返回此字符,加到字符串D里。D:AB;
返回根节点,继续读。
第五个数是0,往左走:
第六个数是1,往右走:
第七个数是1,往右走:
读到有字符的节点,返回此字符,加到字符串D里。D:ABR;
返回根节点,继续读。
如此类推,直到读完所有压缩后的数据S为止。
压缩与解压都搞定了之后 我们需要先把原数据读一遍,并把每个字符出现的次数记录下来。如:
ABRACADABRA!中,A出现了5次;B出现了2次;C出现了1次;D出现了1次;R出现了2次;!出现了1次。
理论上,出现频率越高的字符,我们给它一个占用空间越小的值,这样,我们就可以有最佳的压缩率
由于哈夫曼压缩算法这块涉及内容较多 ,文章篇幅很长;全文全方面讲解了Compose布局的各方面知识。更多Android前言技术进阶,我自荐一套《 完整的Android的资料,以及一些视频课讲解 》 现在私信发送“进阶”或者“笔记”即可免费获取
最后我想说:
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们
技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面
Android 架构师之路还很漫长,与君共勉
⑶ 求C++简单文件压缩程序,用基本算法实现
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void main()
{
ifstream infile("c:\\1.txt");//自己改文件名
ofstream outfile("c:\\2.txt");
char cCurrent,cPre;
int iCount=0;
cPre=-1;
while(infile>>cCurrent)
{
if(cCurrent=='\n') continue;
if(cPre==-1) cPre=cCurrent;
if(cPre==cCurrent)
{
iCount++;
}
else
{
if(cPre>='0'&&cPre<='9')
outfile<<iCount<<'*'<<cPre<<' ';
else
outfile<<iCount<<cPre<<' ';
cPre=cCurrent;
iCount=1;
}
}
if(cPre>='0'&&cPre<='9')
outfile<<iCount<<'*'<<cPre<<' ';
else
outfile<<iCount<<cPre<<' ';
infile.close();
outfile.close();
}
⑷ 二进制压缩算法有哪些
二进制数据压缩算法二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。
20世纪被称作第三次科技革命的重要标志之一的计算机的发明与应用,因为数字计算机只能识别和处理由‘0’。‘1’符号串组成的代码。其运算模式正是二进制。19世纪爱尔兰逻辑学家乔治布尔对逻辑命题的思考过程转化为对符号“0‘’。‘’1‘’的某种代数演算,二进制是逢2进位的进位制。0、1是基本算符。因为它只使用0、1两个数字符号,非常简单方便,易于用电子方式实现。
二进制压缩
在编程时遇到每个数据只有两种状态,且 dfs 或者 bfs 时遍历时间复杂度高时,可以采用二进制压缩数据,尤其是二维数组。LZFSE
1,zlib和gzip都对deflate进行了封装,比deflate多了数据头和尾
1,苹果开源了新的无损压缩算法 LZFSE ,该算法是去年在iOS 9和OS X 10.10中 引入 的。按照苹果公司的说法,LZFE的压缩增益和ZLib level 5相同,但速度要快2~3倍,能源效率也更高。
LZFSE基于Lempel-Ziv,并使用了 有限状态熵编码,后者基于Jarek Duda在
非对称数字系统(ANS)方面所做的熵编码工作。简单地讲,ANS旨在“终结速度和比率的平衡”,既可以用于精确编码,又可以用于快速编码,并且具有数据加密功能。使用ANS代替更为传统的
Huffman和 算术编码方法的压缩库 越来越多,LZFSE就位列其中。
显然,LZFSE的目标不是成为最好或最快的算法。事实上,苹果公司指出,
LZ4的压缩速度比LZFSE快,而 LZMA提供了更高的压缩率,但代价是比Apple
SDK提供的其他选项要慢一个数量级。当压缩率和速度几乎同等重要,而你又希望降低能源效率时,LZFSE是苹果推荐的选项。
GitHub上提供了LZFSE的参考实现。在MacOS上构建和运行一样简单:
$ xcodebuild install DSTROOT=/tmp/lzfse.dst
如果希望针对当前的iOS设备构建LZFSE,可以执行:
xcodebuild -configuration “Release” -arch armv7 install DSTROOT=/tmp/lzfse.dst
除了 API文档之外,苹果去年还提供了一个 示例项目,展示如何使用LZFSE 进行块和流压缩,这是一个实用的LZFSE入门资源。
LZFSE是在谷歌 brotli之后发布的,后者在去年开源。与LZFSE相比,brotli 似乎是针对一个不同的应用场景进行了优化,比如压缩静态Web资产和Android APK,在这些情况下,压缩率是最重要的。
⑸ 数据流压缩原理和数据压缩Zlib的实现
压缩的本质就是去冗余,去除信息冗余,使用最短的编码保存最完整的数据信息。所以对于不同的场景,压缩采用的算法也因时制宜,比如视频和图片可以采用有损压缩,而文本数据采用无损压缩。压缩率又取决于信息的冗余度,也就是内容中重复的比例。那些均匀分布的随机字符串,压缩率会降到最低,即香农限
deflate是zip文件的默认算法。它更是一种数据流压缩算法。
LZ77压缩算法采用字典的方式进行压缩,是一种简单但是很高效的数据压缩算法。其方式就是把数据中一些可以组织成短语的字符加入字典。维护三个概念: 短语字典、滑动窗口、向前缓冲区
压缩的逆过程,通过解码标记和保持滑动窗口中的符号来更新解压数据。当解码字符被标记:将标记编码成字符拷贝到滑动窗口中,一步一步直到全部翻译完成
在流式传输中,不定长编码数据的解码想要保持唯一性,必须满足唯一可以码的条件。而异前缀码就是一种唯一可译码的候选,当然这样会增加编码的长度,却可以简化解码。
huffman编码是一种基于概率分布的贪心策略最优前缀码。huffman编码可以有效的压缩数据,压缩率取决于数据本身的信息冗余度
计算数据中各符号出现的概率,根据概率从小到大,从下往上反向构建构造码树,这样最终得到的编码的平均长度是最短的。同时也是唯一可译的
解读:在一开始,每一个字符已经按照出现概率的大小排好顺序,在后续的步骤中,每一次将概率最低的两棵树合并,然后用合并后的结果再次排序(为了找出最小的两棵树)。在gzip源码中并没有专门去排序,而是使用专门的数据结构(比如最小堆或者红黑树)。
使用优先队列实现huffman树,最后基于Huffman树最终实现文件压缩。
具体步骤:
gzip = gzip 头 + deflate 编码的实际内容 + gzip 尾
zlib = zlib 头 + deflate 编码的实际内容 + zlib 尾
压缩之前:初始化各种输入输出缓冲区;
压缩:我们可以不断往这些缓冲区中填充内容,然后由deflate函数进行压缩或者indeflate函数进行解压
总结:在调用deflate函数之前,应用程序必须保证至少一个动作被执行(avail_in或者avail_out被设置),用提供更多数据或者消耗更多的数据的方式。avail_out在函数调用之前千万不能为零。应用程序可以随时消耗被压缩的输出数据
⑹ 压缩采样的算法是怎么描述的
ADPCM(Adaptive
Differential
Pulse
Code
Molation),是一种针对
16bits(
或8bits或者更高)
声音波形数据的一种有损压缩算法,它将声音流中每次采样的
16bit
数据以
4bit
存储,所以压缩比
1:4.
而且压缩/解压缩算法非常简单,所以是一种低空间消耗,高质量高效率声音获得的好途径。保存声音的数据文件后缀名为
.AUD
的大多用ADPCM
压缩。
ADPCM
主要是针对连续的波形数据的,保存的是波形的变化情况,以达到描述整个波形的目的,由于它的编码和解码的过程却很简洁,列在后面,相信大家能够看懂。
8bits采样的声音人耳是可以勉强接受的,而
16bit
采样的声音可以算是高音质了。ADPCM
算法却可以将每次采样得到的
16bit
数据压缩到
4bit
。需要注意的是,如果要压缩/解压缩得是立体声信号,采样时,声音信号是放在一起的,需要将两个声道分别处理。
PCM是脉冲编码调制的意思。AD是自适应增量的意思。
严格说来,ADPCM不是压缩方法。他的主要思想是,用差值替代绝对值。举个例子,全班同学平均身高175CM:其中,我的身高170CM,这就是PCM方法;我的身高和平均值相比为-5cm,这就是DPCM,我的身高跟前一位同学相比为-10CM,前一位同学有多高我不知道他多高,你问他,这是ADPCM。比方不是太准确,大概就是这个意思。
在大多数情况下,数据值与平均值相差不大,所以用差值替代绝对值可以节省空间。
很高兴回答楼主的问题
如有错误请见谅
⑺ 压缩文件的算法
主要是看文件格式,像rmvb等格式都是已经压缩过的了,再压空间不大,还有就是独立格式文件,一般系统无法识别,并且文件名比较怪的都是别人独立开发的格式,这些也没什么压缩空间,算法你要看那格式种了,系统常见的文件压缩算法都是
ZIP文件的总体格式
分文件头信息+文件压缩数据
中心目录+中心目录记录结束符
1.分文件头信息:
字节数 描述
4 分文件头信息标志(0x04034b50)
2 解压缩所需版本
2 通用比特标志位(置比特0位=加密;置比特1位=使用压
缩方式6,并使用8k变化目录,否则使用4k变化目录;置比特2位=使用压
缩方式6,并使用3个ShannonFano树对变化目录输出编码,否则使用2个
ShannonFano树对变化目录输出编码,其它比特位未用)
2 压缩方式(0=不压缩,1=缩小,2=以压缩因素1缩小,3=以
压缩因素2缩小,4=以压缩因素3缩小,5=以压缩因素4缩小,6=自展)
2 文件最后修改时间
2 文件最后修改日期
4 32位校验码
4 压缩文件大小
4 未压缩文件大小
2 文件名长
2 扩展段长
? 文件名(不定长)
? 扩展段(不定长)
2.中心目录结构
文件头信息...中心目录记录结束符
文件头:
字节数 描述
4 中心文件头信息标志(0x02014b50)
2 主机操作系统(高位字节表示主机操作系统,低位字
节表示ZIP压缩软件版本号,其值除以10表示主版本号,其值模10表示
次版本号。0=MS-DOS,OS/2 FAT文件系统,1=Ami ga,2=VMS,3=Unix及
变种,4=VM/CMS,5=AtariST,6=OS/2 HPFS,7=Macintosh,8=Z-System,9
=C P/M,10-255未用)
2 解压缩所需版本
2 通用比特标志
2 压缩方式
2 文件最后修改时间(用标准的MS-DOS时间日 期格式
编码)
2 文件最后修改日期
4 32位校验码(使用David Schwaderer的CRC-32算法产
生)
4 压缩文件大小
4 未压缩文件大小
2 文件名长
2 扩展段长
2 文件注释长(分别为文件名长,扩展段,注释 段,小于
64K)
2 磁盘起始号(本文件在磁盘中的起始号)
2 内部文件属性(最低位若置1,表示为ASC文本,否则为
二进制数据,其它位未用)
4 外部文件属性(依赖于主机操作系统)
4 分文件头相对位移
? 文件名(不定长)
? 扩展段(不定长,用于未来扩展,低版本为0长)
? 文件注释(不定长)
3.中心目录记录结束符
字节数 描述
4 中心目录标记结束符(0x06054b50)
2 磁盘号(其中包括中心目录结束记录)
2 磁盘中心目录起始号
2 磁盘中心目录入口总数
2 中心目录入口总数(ZIP文件中的文件总数)
2 整个中心目录大小
4 关于起始磁盘号的中心目录初始偏移
2 ZIP文件注释长度
? ZIP文件注释(不定长)
加密方法
PKZIP中使用的加密方法由Roger Schlafly提供。ZIP文件在解压
缩前必须先解密。每个加密文件具有一个12字节的加密文件头扩展信
息,存储于数据区的起始位置,加密前先设置一个起始值,然后被三个3
2位的密钥加密。密钥被使用者提供的口令初始化。12个字节加密之
后,由PKZIP的伪随机数产生方法,结合PKZIP中使用CRC-32算法对密钥
进行更新。
具体实施分为三步:
1.用口令对三个32位密钥初始化。
K(0)=305419896,K(1)=591751049,K(2)=878082192
循环 for i=0 to length(password)-1
调用更新密钥函数 update_keys(password(i))
结束循环(循环口令长度次)
其中更新密钥函数为:
update_keys(char):
Key(0)=crc32(key(0),char)
Key(1)=Key(1)+(Key(0)& 000000ffH)
Key(1)=Key(1)*134775813+1
Key(2)=crc32(Key(2),Key(1)〉〉24)
end update_keys
CRC32函数中,给定一个4字节的CRC值和一个字符,返回一个由CRC
-32算法更新的CRC。具体为:
crc32(c,b)=crc32tab[(c^b)&0xff]^(c>>8),crc32tab[256]的值
为固定的256个4字节数。
2.读取并加密12字节的加密头,再次对密钥进行初始化。
将12个字节的加密头读入缓冲区buffer(0)至buffer(11),循环fo
r i=0 to 11
C=buffer(i)^decrypt_byte()
update_keys(C)
buffer(i)=C
结束循环(循环12次)
其中的decrypt_byte()函数为:
unsigned char decrypt_byte()
local unsigned short temp
temp=Key(2)¦2
decrypt_byte=((temp*(temp^1))>>8)&0xff
end decrypt_byte
该步结束后,缓冲区中最后的二个字节buffer(10)和buffer(11)
将成为加密文件校验码的二个最高位(按低至高顺序存放)。对ZIP加
密文件进行解压缩前,PKUNZIP软件将使用者提供的口令按上述二个步
骤进行处理,得到的结果与校验码的二个高位字节进行比较,只有当提
供了正确的口令时,结果一致,才能进行后续的解压缩过程,否则,PKZI
P报告错误信息,程序自动结束。
3.读取压缩的数据流并以加密密钥对其进行加密。
压缩数据流按下述过程加密:
循环 直至数据流结束
C=数据流的一个字节
temp=C^decrypt_byte()
update_keys(temp)
输出temp
结束循环
⑻ 常用的数据压缩算法有哪些
基本的分为两大类:有损和无损。
有损压缩:主要是一些量化算法,比如a率,u率,lloyds最优量化。
无损压缩:主要是一些编码算法,比如子带编码,差分编码,哈夫曼编码等。
另外时频变换虽然没压缩效果,但是是很好的压缩工具,比如fft,dct等。
最后就是压缩感知稀疏重建等。