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

来源:互联网 发布:数据通信与网络第四版 编辑:程序博客网 时间:2024/06/07 03:12

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

本来上周就打算写的,不过孩子连续高烧,住院了一个礼拜。一个礼拜没回家,还写什么博客。
虽然花了不少钱,好在孩子也恢复过来了,继续努力,挣钱养家(ps:医院真心贵。~)

言归正传,其实今天这篇博客,是一个中间产物,因为在研究热更新,然后就想自己写一套,
下载部分用了curl库,但是文件打包,感觉用zip感觉差点意思,就作死的去研究tar.xz这种格式。
说实话几天过来,感觉到想搞点啥东西,不会英文真是费劲,只能靠悟的 = =、


LZMA

首先一开始研究的是 XZ Utils,在其主页上明显的放着LZMA SDK。
然后 点进去,直接就跑到 7z 的官网了,后来才得知7z也用的是这种算法。。。。
甚至还有对LZMA进行多线程和压缩时间优化的LZMA2算法,不过并没有提供独立lib,
自己搞一通费劲的要死,所以直接选用了LZMA。

其实我的需求并不是算法本身,而是它压缩数据的能力,所以具体算法我并没有过多的研究,
有兴趣的话可以自行研究一下。 不过大致上是对重复序列的特殊处理,可结合下图体会一下。
这里写图片描述
这里写图片描述
可以看到上图基本上将算法本身发挥到极致,5M的数据压缩到800字节左右。
而下图明显无序,所以压缩效果就并没有那么明显了。

lib只提供了,一个压缩函数和一个解压函数,十分难用,所以我进行了一下二次封装。
一些压缩解压涉及到的数据都拼到字节流里了,所以看到了十分爽朗的接口~0~


文件压缩

其实我们经常会用到以rb/wb的形式进去文件操作,一是处理起来简单,二是也算一种简单的加密。
fopen、fread、fwrite,当以二进制格式操作的时候,操作的就是字节流。
所以不难想到,我们可以把文件先读进内存,然后再压缩字节流,然后再写会硬盘。
这样就实现了对文件的压缩,反之则是文件的解压。

    cout << "\n\npart2:" << endl;    Byte* buff = nullptr;    size_t baseLen1 = 0;    size_t baseLen2 = 0;    size_t newlen = 0;    FILE* fp1 = fopen("../src/EOS.tar", "rb");    if (fp1)    {        fseek(fp1, 0, SEEK_END);        size_t file_len = ftell(fp1);        baseLen1 = file_len;        buff = new Byte[file_len];        fseek(fp1, 0, SEEK_SET);        fread(buff, file_len, 1, fp1);        fclose(fp1);        newlen = LZER->code(buff, file_len);        delete[] buff;        buff = new Byte[newlen];        LZER->copyCodeBuff(buff, newlen);        FILE* fp2 = fopen("../src/EOS.tar.xz", "wb");        if (fp2)        {            fwrite(buff, newlen, 1, fp2);            fclose(fp2);            delete[] buff;        }    }    FILE* fp3 = fopen("../src/EOS.tar.xz", "rb");    if (fp3)    {        fseek(fp3, 0, SEEK_END);        size_t file_len = ftell(fp3);        buff = new Byte[file_len];        memset(buff, 0, file_len);        fseek(fp3, 0, SEEK_SET);        fread(buff, file_len, 1, fp3);        fclose(fp3);        Byte a = buff[file_len - 1];        newlen = LZER->decode(buff, file_len);        delete[] buff;        buff = new Byte[newlen];        LZER->copySrcBuff(buff, newlen);        baseLen2 = newlen;        FILE* fp4 = fopen("../src/EOS_2.tar", "wb");        if (fp4)        {            fwrite(buff, newlen, 1, fp4);            fclose(fp4);            delete[] buff;        }    }

这里写图片描述
执行结果如图,不过因为把一些数据直接拼接到了字节流中,所以用winrar之类压缩软件是查看不了
tar.xz后缀的这个文件的。如果使用xz命令进行打包的话,用winrar是可以直接双击查看的。

不过不难看出这种算法,并没有涉及文件操作,所以要实现多文件或递归文件夹压缩,还要解决
tar命令的压缩和解压等问题,研究问题,总会遇到坎坷的。。。

不过可以试想一下,可以用此算法为基础做多文件的拼接的实现,因为都是字节流吗,当然可以用
一个更大的容器把他们都塞进去,记录其起始位置,和文件大小,再对其进行拆解。

比如:
fileName%startPos%fileLen【分隔符】fileName%startPos%fileLen

【FList】eos.lua%100%800!cpp/eos.cpp%901%400!...#FList】然后后边是文件字节流...最后再来点加密解密的信息

不过中间又会遇到多少坑就不得而知了=、=


工具奉上

使用时,dll文件放到exe同级,然后调用文件 只要加上下面三句就可以了。

#include "liblzma/LzmaLib.h"#include "liblzma/LzmaCoder.h"#pragma comment(lib,"LZMA.lib")

有需求兄弟们,有福了,不用自己折腾了~

> git clone git@github.com:Git-EOS/lzma.git

本来想用云盘的,不值为何分享不出连接,各种404,无奈只好上git


总结

说了这是中间产物,再研究下7z的库。或者tar的解压。不过扛不住就只能换zip的库了。
毕竟cocos有一套热更代码,可以搬运,难度小上不少=。=
一起学习,一起进步~

See Again~
之前
真爱无价,欢迎打赏~
这里写图片描述

0 0