最近项目中遇到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. Java 四种引用类型:强引用、软引用、弱引用、虚引用
  2. TensorFlow学习笔记(九)tf搭建神经网络基本流程
  3. Dubbo(七)之自动加载环境变量
  4. mysql命令行导入url_Mysql 导入数据,推荐Source命令,太快了
  5. layui时间日期控件使用
  6. 恒企自考_自考,一个月时间要怎么复习?
  7. fidde调试手机_实操:手机上用Fiddler调试页面(嘎)
  8. C++ 採集音频流(PCM裸流)实现录音功能
  9. ios app被自己从应用商店下架后可以再恢復上架吗
  10. “独裁者”Google:开发者别无他选!| 极客头条
  11. game with probability problem
  12. arcgis中python批处理_基于Python的ArcGIS空间数据格式批处理转换工具开发
  13. python函数式编程:apply, map, lambda和偏函数
  14. 关闭eslink:报错:Unexpected tab character no-tabs
  15. 今日芯声 | 马赛克一键变高清!神奇的AI“无损放大”工具
  16. 半导体芯片行业的运作模式(IDM/Fabless/Foundry模式)
  17. wpf给模板控件添加事件一
  18. Java查找算法-17-二分查找
  19. 深度学习在训练时对图片随机剪裁(random crop)
  20. 手机屏幕坐标获取方法

热门文章

  1. zemax设置 像方远心_像方远心光学系统具有以下特征
  2. 最新瑞芯微四核芯片RK3288开源开发板
  3. 云e办(后端)——项目介绍及搭载项目
  4. JAVAWEB增删改查武林秘籍
  5. 用HTML编写携程旅行,StaticHtmlPage(仿照携程写的静态网页)
  6. java实现连接linux,JAVA实现远道SSH连接linux并执行命令
  7. 个人购买云服务器问题 ?
  8. linux pppd源码下载_linux pppd脚本配置(转载)
  9. 聊一聊C语言位域/位段
  10. 记账软件分享,教你如何记账并管理所有账目