压缩算法_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文件编译的问题,但是我懒的配置了,先放着吧;

  二是解压成源文件之后,解压出来的文件结尾虽然没有数据丢失但是会有部分空格多余,需要丢弃,先放着吧;

  三是读写接口可以优化,加上返回值判断,也放着把;

posted @ 2024-02-02 21:15  caesura_k  阅读(307)  评论(0编辑  收藏  举报