硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1124|回复: 4
收起左侧

[ZLG EasyARM-RT1052] RT1052+zlib分段解压缩

[复制链接]

5

主题

5

回帖

20

积分

新手上路

积分
20
发表于 2025-1-9 20:14:12 | 显示全部楼层 |阅读模式
我用sd卡fatfs做文件系统,参考usb_device_msc_sdcard将sd卡做u盘,然后修改ram我是参考他的 IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小_dtcm和itcm替换sram-CSDN博客 ,然后zlib源码的zutil.c内存申请接口改成了正点原子的,用的数组放到大一点的ram里我给了150k


参考这个:
https://gitcode.com/open-source- ... ource=tools_gitcode

这俩啥作用也不太清楚,MAX_WBITS配到26-31就是gzip了

  • /**
  • * 分段解压函数,实现了封装zlib inflate解压缩函数分多次执行解压大文件功能
  • * 参数:
  • *      output 解压文件输出位置
  • *      output_size 单次输出解压数据最大长度
  • *      input 单次解压的zip文件数据
  • *      input_size 单次解压zip文件数据长度
  • * 说明:
  • *      执行过程:首次执行时创建stream结构体,用于执行zlib解压功能,初始化解压,记录单次zip数据长度 数据,单次输出位置 单次输出最大文件量(单次解压后最大大小,
  • *                一般要足够大,或者可以小一点填满后直接处理了然后再接下一包)
  • *
  • *      stream.avail_out:每次解压后它会减去解压量的大小
  • *      stream.target_out:它会累计解压后的总大小,直到inflateEnd清除
  • *      
  • *      在此处实现时保证outputsize足够大,以满足执行一次之后再处理数据
  • *      
  • *      #define MAX_WBITS   30  // 开窗大小 默认15 32k需要2个32k的RAM,25---31 开启gzip windows下可以解压的格式,在此使用了30
  • *      #define MEM_LEVEL   6  // 压缩等级 默认6
  • */
  • int deflate_uncompress(char *output, uLong output_size, uLong *count_output_size,const char *input, uLong input_size)
  • {
  •     static uint8_t ifFirstStep = 1; // 记录是否第一次执行,在结束时恢复
  •     static z_stream stream;
  •     volatile int ret = 0;
  •     Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */
  •     // 第一次初始化stream
  •     if (ifFirstStep)
  •     {
  •         ifFirstStep = 0; // 清除第一次执行记录
  •         stream.zalloc = (alloc_func)0;
  •         stream.zfree = (free_func)0;
  •         stream.opaque = (voidpf)0;
  •         ret = inflateInit(&stream); // 初始化解压
  •         if (ret != Z_OK)
  •         {
  •             boardConfigDebugLogout("deflate_uncompress inflateInit err\r\n");
  •             return-1;
  •         }
  •     }
  •     stream.avail_in = input_size; // 单次输入zip文本长度
  •     stream.next_in = (Bytef *)input; // 单次数据
  • #if 0 // 在此实现单次无法解压一包数据
  •     do
  •     {
  •         // 记录输出参数
  •         
  •         // 解压,判错
  •         
  •         // 处理一次解压的数据
  •         // 判断是否结束
  •     }while(stream.avail_out == 0); // 若单次输入数据没有解压完毕,则继续解压直到解压完成
  • #else
  •     stream.next_out = (Bytef *)output; // 单次输出,保证足够大
  •     stream.avail_out = output_size; // 记录本次输出最大量,保证足够大
  •     ret = inflate(&stream, Z_NO_FLUSH);
  •     if (ret != Z_OK)
  •     {
  •         if(ret != Z_STREAM_END)
  •         {
  •             boardConfigDebugLogout("deflate_uncompress inflate err\r\n");
  •             ifFirstStep = 1;
  •             return-1;
  •         }
  •         else
  •         {
  •             boardConfigDebugLogout("deflate_uncompress inflate end success\r\n");
  •             inflateEnd(&stream);
  •         }
  •     }
  • #endif
  •     *count_output_size = stream.total_out; // 记录输出的累计量
  •     if(ret == Z_STREAM_END)
  •     {
  •         ifFirstStep = 1;
  •         return 1;
  •     }
  •     return 0;
  • }
  • /**
  • * 输入解压文件以及解压路径
  • * 通过文件系统循环执行解压操作,达到解压大文件功能
  • * 函数使用两个 读文件buf 解压保存buf
  • * 说明:
  • *      执行过程:打开两个文件 一个zip 一个解压后待写入文件,单次读1024 循环-64字节解压-写入 直到结束为止
  • */
  • FIL fp1;
  • FIL fp2;
  • __attribute__((section("ITCRAMAccess"))) char FILE_READ_BUF[10*1024] = {0};
  • __attribute__((section("OCRAMAccess"))) char BUF_10K[1024*10] = {0};
  • int32_t fatFsZipUncompress(char *inpath,char *outpath)
  • {
  •     uint32_t fileSize = 0;
  •     uint32_t fileReadTrueSize = 0;
  •     uint32_t fileWriteTrueSize = 0;
  •     uint32_t onceWriteSize = 0; // 单次写文件大小
  •     uint32_t uncompressSizeL = 0; // 记录上次解压大小累计
  •     uint32_t uncompressSizeN = 0; // 记录本次解压大小累计
  •     uint32_t onecircleTimes = 0; // 单次读取需要解压写多少次
  •     uint32_t onecircleLastSize = 0; // 单次循环最后一次文件长度
  •     const uint32_t ONCELEN = 64; // 单次64字节zip数据
  •     const uint32_t ONCE_READLEN = 1024;
  •     FRESULT fileRes;
  •     int32_t res = 0;
  •    
  •     // fileRes = FileOpen(inpath,ONLY_READ,&fileIndex_read);
  •     fileRes = f_open(&fp1,FA_READ);
  •     if(fileRes != FR_OK)
  •     {
  •         return -1;
  •     }
  •     fileSize = f_size(&fp1);
  •     if(fileSize == 0)
  •     {
  •         boardConfigDebugLogout("fatFsZipUncompress file size 0\r\n");
  •         f_close(&fp1);
  •         return -1;
  •     }
  •     fileRes = f_open(&fp2,FA_WRITE|FA_OPEN_ALWAYS);// 没有则创建
  •     if(fileRes != FR_OK)
  •     {
  •         return -1;
  •     }
  •     // 执行循环读文件,并循环解压写入
  •     for(;;)
  •     {
  •         memset(FILE_READ_BUF,0,sizeof(FILE_READ_BUF)); // 清空读文件buf
  •         fileRes = f_read(&fp1,FILE_READ_BUF,ONCE_READLEN,&fileReadTrueSize);
  •         if(fileRes != FR_OK)
  •         {
  •             f_close(&fp1);
  •             f_close(&fp2);
  •             return -1;
  •         }
  •         
  •         // 需要解压写多少次
  •         if(fileReadTrueSize % ONCELEN)
  •         {
  •             if(fileReadTrueSize < ONCELEN) // 不足ONCELEN,只有一次
  •             {
  •                 onecircleTimes = 1;
  •                 onecircleLastSize = fileReadTrueSize;
  •             }
  •             else // 多次且最后需要额外加一次
  •             {
  •                 onecircleTimes = fileReadTrueSize/ONCELEN + 1;
  •                 onecircleLastSize = fileReadTrueSize % ONCELEN;
  •             }
  •         }
  •         else // 刚好整数次数
  •         {
  •             onecircleTimes = fileReadTrueSize/ONCELEN;
  •             onecircleLastSize = ONCELEN;
  •         }
  •         // 循环指定次数 解压 写文件
  •         for(uint32_t i = 0; i < onecircleTimes; i++)
  •         {
  •             if(i == onecircleTimes-1) // 单次循环的最后一次
  •             {
  •                 res = deflate_uncompress(BUF_10K,sizeof(BUF_10K),&uncompressSizeN,FILE_READ_BUF + (i*ONCELEN),onecircleLastSize);
  •             }
  •             else
  •             {
  •                 res = deflate_uncompress(BUF_10K,sizeof(BUF_10K),&uncompressSizeN,FILE_READ_BUF + (i*ONCELEN),ONCELEN);
  •             }
  •             if(res < 0)
  •             {
  •                 boardConfigDebugLogout("fatFsZipUncompress deflate_uncompress err\r\n");
  •                 f_close(&fp1);
  •                 f_close(&fp2);
  •                 return -1;
  •             }
  •             onceWriteSize = uncompressSizeN - uncompressSizeL; // 计算需要写入的大小
  •         
  •             // 写入
  •             fileRes = f_write(&fp2,BUF_10K,onceWriteSize,&fileWriteTrueSize);
  •             if(fileRes != FR_OK)
  •             {
  •                 boardConfigDebugLogout("fatFsZipUncompress f_write err\r\n");
  •                 f_close(&fp1);
  •                 f_close(&fp2);
  •             }
  •             uncompressSizeL = uncompressSizeN; // 记录大小
  •         }
  •         if(fileReadTrueSize <= ONCELEN) // 文件已经读完了
  •         {
  •             if(res == 1)
  •             {
  •                 break; // 结束
  •             }
  •             else
  •             {
  •                 boardConfigDebugLogout("fatFsZipUncompress end err\r\n");
  •                 f_close(&fp1);
  •                 f_close(&fp2);
  •                 return -1;
  •             }
  •         }
  •     }
  •     f_close(&fp1);
  •     f_close(&fp2);
  •     boardConfigDebugLogout("fatFsZipUncompress success\r\n");
  •     return 0;
  • }




还能在缩小点这个zlib吗?应该怎么做,还有电脑上压缩软件压出来zlib解压不了还要用gzip压缩工具是因为格式吗


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-1-10 08:27:32 | 显示全部楼层
帮顶,没用过zlib
回复

使用道具 举报

5

主题

5

回帖

20

积分

新手上路

积分
20
 楼主| 发表于 2025-1-10 10:42:35 | 显示全部楼层
回复

使用道具 举报

5

主题

5

回帖

20

积分

新手上路

积分
20
 楼主| 发表于 2025-1-24 10:25:44 | 显示全部楼层
这是解压压缩文件夹的,fatfs,外置sdram,有很多问题还没解决,网上资料也找不到
/**
* minizip解压压缩文件夹,测试去除文件数据buf大概需要使用...不知道300k吧... 目前有8m ram用 所以任性给了
* 组合minizip接口实现多文件,小文件解压缩(没有分包处理),保证ram空间足够
* 函数每解压一个文件都重新开关了压缩包并清除了之前的数据,因为每解压四个文件总是出现 DATA_ERROR(zlib的故障码)
* 如果写入文件与读取文件内容对不上就重新解压重新写(发现随机出现写的数据不对)
* 过程:
*      打开压缩包,获取信息记录信息,关闭压缩包
*      (错误重新写跳转位置)打开压缩包,找到第一个,判断是否需要往后找,拿名字,解压,写(错误跳到重新写)
*      释放,关文件等操作然后继续循环
*      结束
*/
int32_t unzip_file(void)
{
    char *p_unzipfileName = NULL; // 用来获取文件名称
    char *p_readBuf = NULL; // 动态申请读空间指针
    char *p_writeBuf = NULL; // 动态申请读空间指针
    int8_t fileIndex = 0;
    static uint8_t fileNUM = 0; // 压缩包包含文件个数
    static uint8_t nextDealNum = 0; // 处理的文件序号
    // const uint32_t onceSize = 10*1024; // 单次最大10k
    // uint32_t lastSize = 0; // 最后一次解压大小
    // uint32_t uncompressTimes = 0; // 单个文件解压次数
    uint32_t readSize = 0;
    uint32_t writeSize = 0;
    int32_t ret = 0;
    unzFile unzipFile;
    unz_global_info64 global_info; // 获取压缩包信息
    unz_file_info64 file_info;

    unzipFile = unzOpen2_64("1:txt.zip",&zipffunc); // 打开压缩包
    if(NULL == unzipFile)
    {
        return -1;
    }

    if(UNZ_OK != unzGetGlobalInfo64(unzipFile,&global_info))
    {
        unzClose(unzipFile);
        return -1;
    }
    fileNUM = global_info.number_entry; // 记录文件个数
    nextDealNum = 0; // 从0开始

    if(UNZ_OK != unzGoToFirstFile(unzipFile))
    {
        unzClose(unzipFile);
        return -1;
    }
    unzClose(unzipFile); // 关闭压缩包,解压过程会再次打开

    for(uint32_t i=0;i<fileNUM;i++)
    {
REDEAL: //=========================== 跳转到此处重新处理该文件
        memset(&file_info,0,sizeof(unz_file_info64)); // 清除记录信息
        memset(FILE_PATH_BUF,0,sizeof(FILE_PATH_BUF));
        memset(unzipFile,0,sizeof(unz64_s));
        unzipFile = unzOpen2_64("1:txt.zip",&zipffunc); // 打开压缩包
        if(NULL == unzipFile)
        {
            return -1;
        }   

        if(UNZ_OK != unzGoToFirstFile(unzipFile))
        {
            unzClose(unzipFile);
            return -1;
        }
        
        for(uint8_t j=0;j<nextDealNum;j++)
        {
            if(unzGoToNextFile(unzipFile) != UNZ_OK)
            {
                unzClose(unzipFile);
                return -1;
            }
        }

        p_unzipfileName = my_malloc(100);

        if(unzGetCurrentFileInfo64(unzipFile,&file_info,p_unzipfileName,100,NULL,0,NULL,0) != UNZ_OK)
        {
            unzClose(unzipFile);
            return -1;
        }

        my_free(p_unzipfileName);

        sprintf(FILE_PATH_BUF,"1:%s",p_unzipfileName);
        ret = FileOpen(FILE_PATH_BUF,WRITE_CREATE,&fileIndex);
        if (ret < 0)
        {
            unzClose(unzipFile);
            return -1;
        }

        if(unzOpenCurrentFile(unzipFile) != UNZ_OK)
        {
            fileCloseFp(fileIndex);
            unzClose(unzipFile);
            return -1;
        }

        p_readBuf = my_malloc(file_info.uncompressed_size);
        p_writeBuf = my_malloc(file_info.uncompressed_size);
        do
        {
            readSize = unzReadCurrentFile(unzipFile, p_readBuf, file_info.uncompressed_size);
            if(readSize)
            {
                mymemcpy(p_writeBuf,p_readBuf,readSize); // TODO 测试时发现读取缓冲区在写文件时总是被意外更改
                FileWritefs(fileIndex, p_writeBuf, readSize, &writeSize);
                if(writeSize != readSize)
                {
                    // 重新创建文件
                    fileCloseFp(fileIndex);
                    my_free(p_readBuf); // 无论如何释放空间
                    my_free(p_writeBuf); // 无论如何释放空间
                    if(unzCloseCurrentFile(unzipFile) != UNZ_OK)
                    {
                        return -1;
                    }
                    unzClose(unzipFile); // 关闭压缩包
                    goto REDEAL; // TODO !!!!注意此处进行了跳转重新处理此文件解压与写入,写入可能失败
                }

                fileCloseFp(fileIndex);

                ret = FileOpen(FILE_PATH_BUF,ONLY_READ,&fileIndex);
                if (ret != 0)
                {
                    unzClose(unzipFile); // 关闭压缩包
                    return -1;
                }
                FileReadfs(fileIndex, BUF_1M, readSize, &writeSize);
                if (ret != 0)
                {
                    fileCloseFp(fileIndex);
                    unzClose(unzipFile); // 关闭压缩包
                    return -1;
                }
                // 对比buf
                for(uint32_t n = 0; n<readSize; n++)
                {
                    if(BUF_1M[n] != p_readBuf[n])
                    {
                        // 重新创建文件
                        fileCloseFp(fileIndex);
                        my_free(p_readBuf); // 无论如何释放空间
                        my_free(p_writeBuf); // 无论如何释放空间
                        if(unzCloseCurrentFile(unzipFile) != UNZ_OK)
                        {
                            unzClose(unzipFile); // 关闭压缩包
                            return -1;
                        }
                        unzClose(unzipFile); // 关闭压缩包
                        goto REDEAL; // TODO !!!!注意此处进行了跳转重新处理此文件解压与写入,写入可能失败
                    }
                }
            }
            else
            {
                break;
            }
        } while (1);

        my_free(p_readBuf); // 无论如何释放空间
        my_free(p_writeBuf); // 无论如何释放空间
        my_free(p_unzipfileName);
        fileCloseFp(fileIndex);
        if(unzCloseCurrentFile(unzipFile) != UNZ_OK)
        {
            unzClose(unzipFile); // 关闭压缩包
            return -1;
        }
        nextDealNum++;
        unzClose(unzipFile); // 关闭压缩包
    }
    return 0;
}
回复

使用道具 举报

5

主题

5

回帖

20

积分

新手上路

积分
20
 楼主| 发表于 2025-1-24 10:29:00 | 显示全部楼层
这是minizip 解压压缩文件包的 需要移植minizip修改它的 文件接口 内存接口 处理掉编译error,使用了外置sdram
有很多问题,网上资料也找不到......
/**
* minizip解压压缩文件夹,测试去除文件数据buf大概需要使用...不知道300k吧... 目前有8m ram用 所以任性给了
* 组合minizip接口实现多文件,小文件解压缩(没有分包处理),保证ram空间足够
* 函数每解压一个文件都重新开关了压缩包并清除了之前的数据,因为每解压四个文件总是出现 DATA_ERROR(zlib的故障码)
* 如果写入文件与读取文件内容对不上就重新解压重新写(发现随机出现写的数据不对)
* 过程:
*      打开压缩包,获取信息记录信息,关闭压缩包
*      (错误重新写跳转位置)打开压缩包,找到第一个,判断是否需要往后找,拿名字,解压,写(错误跳到重新写)
*      释放,关文件等操作然后继续循环
*      结束
*/
int32_t unzip_file(void)
{
    char *p_unzipfileName = NULL; // 用来获取文件名称
    char *p_readBuf = NULL; // 动态申请读空间指针
    char *p_writeBuf = NULL; // 动态申请读空间指针
    int8_t fileIndex = 0;
    static uint8_t fileNUM = 0; // 压缩包包含文件个数
    static uint8_t nextDealNum = 0; // 处理的文件序号
    // const uint32_t onceSize = 10*1024; // 单次最大10k
    // uint32_t lastSize = 0; // 最后一次解压大小
    // uint32_t uncompressTimes = 0; // 单个文件解压次数
    uint32_t readSize = 0;
    uint32_t writeSize = 0;
    int32_t ret = 0;
    unzFile unzipFile;
    unz_global_info64 global_info; // 获取压缩包信息
    unz_file_info64 file_info;

    unzipFile = unzOpen2_64("1:txt.zip",&zipffunc); // 打开压缩包
    if(NULL == unzipFile)
    {
        return -1;
    }

    if(UNZ_OK != unzGetGlobalInfo64(unzipFile,&global_info))
    {
        unzClose(unzipFile);
        return -1;
    }
    fileNUM = global_info.number_entry; // 记录文件个数
    nextDealNum = 0; // 从0开始

    if(UNZ_OK != unzGoToFirstFile(unzipFile))
    {
        unzClose(unzipFile);
        return -1;
    }
    unzClose(unzipFile); // 关闭压缩包,解压过程会再次打开

    for(uint32_t i=0;i<fileNUM;i++)
    {
REDEAL: //=========================== 跳转到此处重新处理该文件
        memset(&file_info,0,sizeof(unz_file_info64)); // 清除记录信息
        memset(FILE_PATH_BUF,0,sizeof(FILE_PATH_BUF));
        memset(unzipFile,0,sizeof(unz64_s));
        unzipFile = unzOpen2_64("1:txt.zip",&zipffunc); // 打开压缩包
        if(NULL == unzipFile)
        {
            return -1;
        }   

        if(UNZ_OK != unzGoToFirstFile(unzipFile))
        {
            unzClose(unzipFile);
            return -1;
        }
        
        for(uint8_t j=0;j<nextDealNum;j++)
        {
            if(unzGoToNextFile(unzipFile) != UNZ_OK)
            {
                unzClose(unzipFile);
                return -1;
            }
        }

        p_unzipfileName = my_malloc(100);

        if(unzGetCurrentFileInfo64(unzipFile,&file_info,p_unzipfileName,100,NULL,0,NULL,0) != UNZ_OK)
        {
            unzClose(unzipFile);
            return -1;
        }

        my_free(p_unzipfileName);

        sprintf(FILE_PATH_BUF,"1:%s",p_unzipfileName);
        ret = FileOpen(FILE_PATH_BUF,WRITE_CREATE,&fileIndex);
        if (ret < 0)
        {
            unzClose(unzipFile);
            return -1;
        }

        if(unzOpenCurrentFile(unzipFile) != UNZ_OK)
        {
            fileCloseFp(fileIndex);
            unzClose(unzipFile);
            return -1;
        }

        p_readBuf = my_malloc(file_info.uncompressed_size);
        p_writeBuf = my_malloc(file_info.uncompressed_size);
        do
        {
            readSize = unzReadCurrentFile(unzipFile, p_readBuf, file_info.uncompressed_size);
            if(readSize)
            {
                mymemcpy(p_writeBuf,p_readBuf,readSize); // TODO 测试时发现读取缓冲区在写文件时总是被意外更改
                FileWritefs(fileIndex, p_writeBuf, readSize, &writeSize);
                if(writeSize != readSize)
                {
                    // 重新创建文件
                    fileCloseFp(fileIndex);
                    my_free(p_readBuf); // 无论如何释放空间
                    my_free(p_writeBuf); // 无论如何释放空间
                    if(unzCloseCurrentFile(unzipFile) != UNZ_OK)
                    {
                        return -1;
                    }
                    unzClose(unzipFile); // 关闭压缩包
                    goto REDEAL; // TODO !!!!注意此处进行了跳转重新处理此文件解压与写入,写入可能失败
                }

                fileCloseFp(fileIndex);

                ret = FileOpen(FILE_PATH_BUF,ONLY_READ,&fileIndex);
                if (ret != 0)
                {
                    unzClose(unzipFile); // 关闭压缩包
                    return -1;
                }
                FileReadfs(fileIndex, BUF_1M, readSize, &writeSize);
                if (ret != 0)
                {
                    fileCloseFp(fileIndex);
                    unzClose(unzipFile); // 关闭压缩包
                    return -1;
                }
                // 对比buf
                for(uint32_t n = 0; n<readSize; n++)
                {
                    if(BUF_1M[n] != p_readBuf[n])
                    {
                        // 重新创建文件
                        fileCloseFp(fileIndex);
                        my_free(p_readBuf); // 无论如何释放空间
                        my_free(p_writeBuf); // 无论如何释放空间
                        if(unzCloseCurrentFile(unzipFile) != UNZ_OK)
                        {
                            unzClose(unzipFile); // 关闭压缩包
                            return -1;
                        }
                        unzClose(unzipFile); // 关闭压缩包
                        goto REDEAL; // TODO !!!!注意此处进行了跳转重新处理此文件解压与写入,写入可能失败
                    }
                }
            }
            else
            {
                break;
            }
        } while (1);

        my_free(p_readBuf); // 无论如何释放空间
        my_free(p_writeBuf); // 无论如何释放空间
        my_free(p_unzipfileName);
        fileCloseFp(fileIndex);
        if(unzCloseCurrentFile(unzipFile) != UNZ_OK)
        {
            unzClose(unzipFile); // 关闭压缩包
            return -1;
        }
        nextDealNum++;
        unzClose(unzipFile); // 关闭压缩包
    }
    return 0;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-11 21:05 , Processed in 0.057260 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表