压缩算法_quicklz使用
1 quicklz
quicklz是单片机上一个常见的压缩算法,具体原理没有文档和hash表的相关基础我就不去深究了;
只需要将fileSrc.txt放在桌面,代码可以使用vscode的mingw直接编译;
2 quicklz源码
quicklz源码就一个c文件一个h文件,标准库要求就一个<string.h>;移植起来比较简单,直接包含头文件即可;
https://gitee.com/RT-Thread-Mirror/quicklz
fileSrc.txt
/***Put this file on Desktop as srcFile for quicklz compress;***/ // attention //1 compress buff no more than 2048 size; //2 because compressed transmit buff need to read qlz algrorithm parameter together for decompress, // and parameter will count into decompressed buff; // may lead to some mistake decompress;
4 quicklz 函数接口
/***main.c**************************************************************************************************/ //vscode直接使用mingw编译的时候没法包含多个c文件编译,需要配置vscode编译路径,不想配先放着; //所以quicklz.c代码需要放到main函数所在c文件中,不然会查找不到; #include <stdio.h> #include <stdlib.h> #include "quicklz.h" #define PATH_FILE_SRC "C:/Users/WINDOWS/Desktop/fileSrc.txt" #define PATH_FILE_CPS "C:/Users/WINDOWS/Desktop/fileCompress.qlz" #define PATH_FILE_DST "C:/Users/WINDOWS/Desktop/fileDst.txt" int qlzCompress(void) { printf("qlzCompress() \n"); FILE *fsrcFile; FILE *fcpsFile; unsigned char psrcTrans[2048] ={0}; unsigned char pdstTrans[2048] ={0}; size_t srcFileLen, cpsFileLen; qlz_state_compress state_compress; //fsrcFile handle; fsrcFile = fopen(PATH_FILE_SRC, "r"); //fsrcFile length; fseek(fsrcFile, 0, SEEK_END); srcFileLen = ftell(fsrcFile); //read fsrcFile >> psrcTrans; printf("srcFileLen:(d)%08d \n",srcFileLen); fseek(fsrcFile, 0, SEEK_SET); fread(psrcTrans, sizeof(char), srcFileLen, fsrcFile); //for(int i =0; i<srcFileLen;i++) printf("%c",psrcTrans[i]); printf("\n"); //fcpsFile handle; fcpsFile = fopen(PATH_FILE_CPS, "w"); //compress psrcTrans >> pdstTrans; cpsFileLen = qlz_compress(psrcTrans, pdstTrans, srcFileLen, &state_compress); printf("cpsFileLen:(d)%08d \n",cpsFileLen); fwrite(pdstTrans, sizeof(char), cpsFileLen, fcpsFile); fclose(fsrcFile); fclose(fcpsFile); return 0; } int qlzDecompress(void) { printf("qlzDecompress() \n"); FILE *fcpsFile; FILE *fdstFile; unsigned char *pcpsTrans; unsigned char *pdstTrans; qlz_state_decompress state_decompress; unsigned int cpsFileLen; unsigned int decpsFileLen; //fcpsFile handle; fcpsFile = fopen(PATH_FILE_CPS, "r"); //fcpsFile length; fseek(fcpsFile, 0, SEEK_END); cpsFileLen = ftell(fcpsFile); //pcpsTrans buff pcpsTrans = (unsigned char *)malloc(cpsFileLen); if(pcpsTrans==NULL){ printf("malloc cps buff fail. \n"); return -2; } //read fcpsFile >> pcpsTrans; printf("cpsFileLen:(d)%08d \n",cpsFileLen); fseek(fcpsFile, 0, SEEK_SET); fread(pcpsTrans, sizeof(char), cpsFileLen, fcpsFile); //for(int i =0;i< cpsFileLen;i++) printf("%02x ",pcpsTrans[i]); printf("\n"); //pdstTrans length; decpsFileLen = qlz_size_decompressed(pcpsTrans); pdstTrans = (unsigned char *)malloc(decpsFileLen); if(pdstTrans ==NULL){ printf("malloc pdstTrans fail. \n"); return -3; } //bcz pcpsTrans read some more qlz para, //so after decompress will have some more space empty in fileDst.txt? bug leave; printf("decpsFileLen:(d)%08d \n",decpsFileLen); decpsFileLen = qlz_decompress(pcpsTrans, pdstTrans, &state_decompress); fdstFile = fopen(PATH_FILE_DST, "w"); fwrite(pdstTrans, sizeof(char), decpsFileLen, fdstFile); fclose(fcpsFile); fclose(fdstFile); free(pcpsTrans); free(pdstTrans); return 0; } int main() { printf("hello \n"); //文件压缩完之后会多出部分qlz的参数,分配内存时需要考虑; //因为解压时是通过读取文件长度来解压的,所以解压后结尾部分会把这部分多出的也解压了;qlz本身小bug?? //这个bug的解决办法是在使用数据的时候只读取解压长度的数据,丢弃掉多余字节; //所以在使用数据的时候,需要通过解压前数据长度来使用; //上面的接口函数只是压缩解压,不涉及数据处理使用; //qlz解压最大不超过4096,需要考虑; //函数内数组不要超出栈空间大小; qlzCompress(); qlzDecompress(); return 0; }
5 文件操作读写模式
前两列判断fopen的操作;后两列判断如果可以执行当前函数操作的话pfile的文件偏移位置;
需要注意的是图中斜杆部分读写无此操作,但执行不会报错,导致不容易发现bug,
通过判断fopen、fread、fwrite返回值来判断文件操作是否成功失败,可以提高代码的健壮性和稳定性;
6 小结
这个接口主要还有三个地方需要优化的;
一是vscode编辑器配置多个c文件编译的问题,但是我懒的配置了,先放着吧;
二是解压成源文件之后,解压出来的文件结尾虽然没有数据丢失但是会有部分空格多余,需要丢弃,先放着吧;
三是读写接口可以优化,加上返回值判断,也放着把;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?