本来上周就打算写的,不过孩子连续高烧,住院了一个礼拜。一个礼拜没回家,还写什么博客。
虽然花了不少钱,好在孩子也恢复过来了,继续努力,挣钱养家(ps:医院真心贵。~)
言归正传,其实今天这篇博客,是一个中间产物,因为在研究热更新,然后就想自己写一套,
下载部分用了curl库,但是文件打包,感觉用zip感觉差点意思,就作死的去研究tar.xz这种格式。
说实话几天过来,感觉到想搞点啥东西,不会英文真是费劲,只能靠悟的 = =、
首先一开始研究的是 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~
之前
真爱无价,欢迎打赏~