最近项目中遇到OTA固件升级,压缩由上位机实现,解压缩在boot启动时,读取固件内容后边解压边加载数据的方式启动。
前期预研了三种压缩方案,分别是lz4、zip、7z,代码仓库放在下面,三者各自的原理可自行百度了解。

  • lz4
  • zip
  • 7z

一、lzma的使用

由于项目中要求对所升级的固件压缩比的最大化,因此选择了7z中的lzma算法,版本为1900

LzmaUtil.c文件中完整实现了针对一个流式文件的压缩以及解压缩。实验环境为Ubuntu20.04。

  1. 编译
    修改Lzma文件夹下的makefile.gcc,将编译器修改为gcc。在当前目录下输入make -f makefile.gcc 编译生成lzma可执行文件
PROG = lzma
CXX = gcc
LIB =
RM = rm -f
CFLAGS = -c -O2 -Wall -D_7ZIP_ST
  1. 压缩
    ./lzma e *要压缩的文件* *目标文件* 第二个参数(e)不区分大小写

    ./lzma e makefile.gcc makefile_compr
    
  2. 解压
    ./lzma d *要解压的文件* *目标文件* 同样,第二个参数不区分大小写

    ./lzma d makefile_compr makefile_decompr
    

解压后可以对比makefile_decompr与原始文件makefile.gcc内容是否一致

二、lzma的深入理解

  1. lzma压缩文件的特征
Offset Size Description0     1   Special LZMA properties (lc,lp, pb in encoded form)1     4   Dictionary size (little endian)5     8   Uncompressed size (little endian). -1 means unknown size13         Compressed data

以二进制的方式打开一个用lzma压缩算法压缩后的文件,其文件格式为文件头(13bytes)+ 压缩数据大小,第一个字节是压缩文件的属性,后四个字节是字典的大小,再往后8个字节是未压缩数据的大小,它们都用小端(little endian)表示。

第一个字节属性,三个取值分别如下:

    name  Range          Descriptionlc  [0, 8]         the number of "literal context" bitslp  [0, 4]         the number of "literal pos" bitspb  [0, 4]         the number of "pos" bits
  1. 代码详解
    简单了解一下lzma压缩后的文件特征,现在回到LzmaUtil.c来看看具体的压缩与解压缩是怎样实现的。
  • main2()
  CFileSeqInStream inStream;CFileOutStream outStream;

这两个结构体可以等同于文件IO中的fread和fwrite函数来理解,用来打开一个文件和向文件中写入内容。接下来是关于入参的一些判断很好理解。通过encodeMode的真假来决定是压缩还是解压缩。

  • Encode() 压缩
static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)

*outStream:压缩后的数据
*inStream:源数据
fileSize:源数据的大小

lzma属性相关参数结构体:

typedef struct _CLzmaEncProps
{int level;       /* 0 <= level <= 9 */UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version(1 << 12) <= dictSize <= (3 << 29) for 64-bit versiondefault = (1 << 24) */int lc;          /* 0 <= lc <= 8, default = 3 */int lp;          /* 0 <= lp <= 4, default = 0 */int pb;          /* 0 <= pb <= 4, default = 2 */int algo;        /* 0 - fast, 1 - normal, default = 1 */int fb;          /* 5 <= fb <= 273, default = 32 */int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */int numHashBytes; /* 2, 3 or 4, default = 4 */UInt32 mc;       /* 1 <= mc <= (1 << 30), default = 32 */unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */int numThreads;  /* 1 or 2, default = 2 */UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.Encoder uses this value to reduce dictionary size */
} CLzmaEncProps;

Encode中设置了lzma的属性,并将其写入文件头然后压缩,这里贴出属性的初始化函数的实现(属性设置的太长了,大家可以自行查看,实现原理很简单)。

void LzmaEncProps_Init(CLzmaEncProps *p)
{p->level = 5;p->dictSize = p->mc = 0;p->reduceSize = (UInt64)(Int64)-1;p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;p->writeEndMark = 0;
}

压缩所用到的结构体CLzmaEnc 大小为123k,因此在单片机上实现压缩功能是很困难

  • Decode() 解压缩
static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)

*outStream:解压后的数据
*inStream:源数据
该函数会首先解析压缩文件的文件头,然后申请解压所需的内存空间,接下来进入Decode2开始解压缩。

static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 unpackSize)

Decode2中解压缩的逻辑不难理解,可以根据自己的硬件资源调整两个缓存的大小,同时需要关注属性设置时字典的大小避免资源不足无法完成解压。

最后,可根据自己项目的实际情况更改文件读写的接口、lzma的属性等参数来实现压缩、解压缩。

7z压缩 lzma流式压缩、解压缩的实现 C语言相关推荐

  1. linux lzma命令,Ubuntu: 压缩与解压缩LZMA文件

    什么是LZMA格式呢?当遇到LZMA格式的压缩文档时我们该怎么解压呢?如果我们想创建LZMA该用什么工具呢?就让我们快速浏览一下吧. 1.什么是LZMA格式 LZMA(Lempel-Ziv-Marko ...

  2. mac 命令行 解压7z文件_命令行压缩解压缩一 7z

    命令行压缩解压缩一 7z 1) 简介 7z,全称7-Zip, 是一款开源软件.是目前公认的压缩比例最大的压缩解压缩软件. 主页:http://www.7-zip.org/ 中文主页:http://7z ...

  3. mac 命令行 解压7z文件_命令行压缩解压7z

    命令行压缩解压一 7z 1) 简介7z,全称7-Zip, 是一款开源软件.是目前公认的压缩比例最大的压缩解压软件.主页:http://www.7-zip.org/中文主页:http://7z.spar ...

  4. java视频压缩 lz4_关于LZMA和LZ4压缩的疑惑解析

    原标题:关于LZMA和LZ4压缩的疑惑解析 这是第112篇UWA技术知识分享的推送.今天我们继续为大家精选了若干和开发.优化相关的问题,建议阅读时间10分钟,认真读完必有收获. UWA QQ群:465 ...

  5. Unity加载优化-将基于LZMA的ab压缩方案修改为LZ4压缩的过程

    # 观前提示 本文适合需要了解LZMA以及LZ4进行ab打包方案同学,以及会将一些资源管理的方案.如果恰好你也用xlua-framework,那就更适合你了. # 优化起因 最近新游戏在Iphone6 ...

  6. lzma和gzip压缩命令简介

    一.lzma LZMA  (Lempel-Ziv-Markov  chain-Algorithm)  基于著名的LZ77压缩算法改进的压缩/解压工具,特点:高压缩率,高解压速度,低内存消耗,lzma命 ...

  7. 【步兵 工具篇】lzma算法,压缩字节流

    [步兵 工具篇]lzma算法,压缩字节流 by EOS. 本来上周就打算写的,不过孩子连续高烧,住院了一个礼拜.一个礼拜没回家,还写什么博客. 虽然花了不少钱,好在孩子也恢复过来了,继续努力,挣钱养家 ...

  8. Java基础19:IO流—缓冲流、转换流、序列化、打印流、压缩流和解压流

    IO流中的一些其他流:缓冲流.转换流.序列化.打印流.压缩流和解压流 1. 缓冲流 IO流除了一些基本的流,还有在此基础上发展出来的一些更强大的流.比如能够高效读写的缓冲流,能够转换编码的转换流,能够 ...

  9. Java基础(二):集合、IO流(Zip压缩输入/输出流等)、File文件类、反射、枚举

    Java基础(一):编译和解释.数据类型.变量作用域.String常用方法.数组.面向对象.异常 Java基础(二):集合.IO流(Zip压缩输入/输出流等).File文件类.反射.枚举 Java异常 ...

最新文章

  1. 1小时学会:最简单的iOS直播推流(番外)运行不起AWLive的demo的同学请看这里
  2. C++ stringstream 简化数据类型转换
  3. 从一个被Tomcat拒绝的漏洞到特殊内存马
  4. linux通过进程名查找进程,Linux下通过进程名获得进程号
  5. 利用DBMS_FILE_TRANSFER传输数据库文件
  6. xshell十大技巧
  7. 如何解决eclipse里面tomcat 8080端口被占用
  8. 如何安装mysql 匹配_学习笔记----安装MySQL
  9. python字符串用法_笔记:python字符串的使用
  10. 组策略设置IE 11的Compatible View
  11. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第3节 两种获取Stream流的方式_3_Stream流中的常用方法_filter...
  12. C语言的源代码文件、目标文件和可执行文件
  13. yyuc视图未更新,控制器修改可以看到,视图无法更新,提示Allowed memory size of exhausted
  14. 应用程序无法正常启动0xc0150002怎么解决
  15. android基础教程:多个页面时如何设置首页
  16. Mac Navicat连接MySQL8.0.11出错:2003 - Can't connect to MySQL server on ……(61 Connection refused)
  17. TLS原理及证书生成
  18. 浅谈机器人控制与仿真设计----RDS和ROS
  19. Ubuntu下安装NS-3图文教程
  20. linux网卡设置详解

热门文章

  1. 绘制圆形 和 椭圆形:边圆形 imageellipse() 、 填充圆形imagefilledellipse()
  2. 高等数学 武忠祥强化班
  3. 街景地图工作是如何工作的
  4. DUTOJ-1205: 对圣杯宝具的威力值
  5. 在电脑双屏使用时,搜狗输入法在别的屏幕(转)
  6. Java执行引擎工作原理:方法调用
  7. CSS:line-height是什么?,height是什么?
  8. 用Flash做点击页面图片切换效果的超级详细教程
  9. [转] 如何用BSP树生成游戏地图
  10. Metal每日分享,调整胶片颗粒感滤镜效果