• cocos lua解压zip文件(支持源文件非zip格式)


    最近遇到需要在cocos中解压zip的需求就了解了下

    以下代码摘自: http://www.cocoachina.com/bbs/read.php?tid=212537

        // Open the zip file
        std::string outFileName = filename;
        unzFile zipfile = unzOpen(outFileName.c_str());
        if (!zipfile){
            CCLOG("can not open downloaded zip file %s", outFileName.c_str());
            return false;
        }
     
        // Get info about the zip file
        unz_global_info global_info;
        if (unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK){
            CCLOG("can not read file global info of %s", outFileName.c_str());
            unzClose(zipfile);
            return false;
        }
     
        const int BUFFER_SIZE = 8192;
        const int MAX_FILENAME = 512;
        
    // Buffer to hold data read from the zip file     char readBuffer[BUFFER_SIZE];       // Loop to extract all files.     uLong i;     for (i = 0; i < global_info.number_entry; ++i){         // Get info about current file.         unz_file_info fileInfo;         char fileName[MAX_FILENAME];         if (unzGetCurrentFileInfo(zipfile, &fileInfo, fileName, MAX_FILENAME, NULL, 0, NULL, 0) != UNZ_OK){             CCLOG("can not read file info");             unzClose(zipfile);             return false;         }           std::string storagePath = destPath;         std::string fullPath = storagePath + fileName;           // Check if this entry is a directory or a file.         const size_t filenameLength = strlen(fileName);         if (fileName[filenameLength - 1] == '/'){             // get all dir             std::string fileNameStr = std::string(fileName);             size_t position = 0;             while ((position = fileNameStr.find_first_of("/", position)) != std::string::npos){                 std::string dirPath = storagePath + fileNameStr.substr(0, position);                 // Entry is a direcotry, so create it.                 // If the directory exists, it will failed scilently.                 if (!createDirectory(dirPath.c_str())){                     CCLOG("can not create directory %s", dirPath.c_str());                     //unzClose(zipfile);                     //return false;                 }                 position++;             }         } else {             // Entry is a file, so extract it.             // Open current file.             if (unzOpenCurrentFile(zipfile) != UNZ_OK) {                 CCLOG("can not open file %s", fileName);                 unzClose(zipfile);                 return false;             }               // Create a file to store current file.             FILE *out = fopen(fullPath.c_str(), "wb");             if (!out) {                 CCLOG("can not open destination file %s", fullPath.c_str());                 unzCloseCurrentFile(zipfile);                 unzClose(zipfile);                 return false;             }               // Write current file content to destinate file.             int error = UNZ_OK;             do {                 error = unzReadCurrentFile(zipfile, readBuffer, BUFFER_SIZE);                 if (error < 0) {                     CCLOG("can not read zip file %s, error code is %d", fileName, error);                     unzCloseCurrentFile(zipfile);                     unzClose(zipfile);                     return false;                 }                   if (error > 0) {                     fwrite(readBuffer, error, 1, out);                 }             } while (error > 0);             fclose(out);         }           unzCloseCurrentFile(zipfile);           // Goto next entry listed in the zip file.         if ((i + 1) < global_info.number_entry) {             if (unzGoToNextFile(zipfile) != UNZ_OK) {                 CCLOG("can not read next file");                 unzClose(zipfile);                 return false;             }         }     }

    使用zlib 的上层封装 minizip 的接口,但是 在ios上会出现非zip后缀的文件,无法读取的尴尬,主要问题出在unzOpen方法。

    看了下 可以使用unzOpenBuffer方法就能避免掉这个问题。就变成了:

        std::string outFileName = filename;    
        ssize_t size = 0;
        unsigned char *zipFileData = FileUtils::getInstance()->getFileData(outFileName, "rb", &size);    
        unzFile zipfile = unzOpenBuffer(zipFileData, size);
        ......

    或者直接用cocos封装好的 ZipFile ,也就是:

        ZipFile *zip = nullptr;
        if (zipFileData) {
            zip = ZipFile::createWithBuffer(zipFileData, size);
        }

     

    这样就ok。同时了解了下zip格式:

     

     

    OffsetBytesContentsDescriptor
    LOCAL FILE HEADER      
    00000000 4 50 4B 03 04 文件头标识(0x04034b50)
    00000004 2 0A 00 解压文件所需 pkware最低版本
    00000006 2 00 00 通用比特标志位
    00000008 2 08 00 压缩方式
    0000000A 2 E1 5D 文件最后修改时间
    0000000C 2 CC 48 文件最后修改日期
    0000000E 4 61 D3 72 09 crc-32校验码
    00000012 4 08 00 00 00 压缩后的大小
    00000016 4 06 00 00 00 未压缩的大小
    0000001A 2 07 00 文件名长度
    0000001C 2 00 00 扩展区长度
    0000001E 6 31 32 33 2E 74 78 74 文件名 123.txt
    FILE DATA      
    00000025 8 33 34 32 36 31 35 03 00 压缩文件数据,此处就是压缩文本文件123.txt压缩后的数据
    Central Directory Header      
    0000002D 4 50 4B 01 02 核心目录文件header标识=(0x02014b50)
    00000031 2 0A 00 压缩所用的pkware版本
    00000033 2 0A 00 解压所需pkware的最低版本
    00000035 2 00 00 通用位标记
    00000037 2 08 00 压缩方法
    00000039 2 E1 5D 文件最后修改时间
    0000003B 2 CC 48 文件最后修改日期
    0000003D 4 61 D3 72 09 CRC-32校验码
    00000041 4 08 00 00 00 压缩后的大小
    00000045 4 06 00 00 00 未压缩的大小
    00000049 2 07 00 文件名长度
    0000004B 2 00 00 扩展域长度
    0000004D 2 00 00 文件注释长度
    0000004F 2 00 00 文件开始位置的磁盘编号
    00000051 2 00 00 内部文件属性
    00000053 4 20 00 00 00 外部文件属性
    00000057 4 00 00 00 00 本地文件header的相对位移
    0000005B 7 31 32 33 2E 74 78 74 目录文件名
    End of central directory record      
    00000062 4 50 4B 05 06 核心目录结束标记(0x06054b50)
    00000066 2 00 00 当前磁盘编号
    00000068 2 00 00 核心目录开始位置的磁盘编号
    0000006A 2 01 00 该磁盘上所记录的核心目录数量
    0000006C 2 01 00 核心目录结构总数
    0000006E 4 35 00 00 00 核心目录的大小
    00000072 4 2D 00 00 00 核心目录开始位置相对于archive开始的位移
    00000076 2 00 00 注释长度

     

     

     

     

     

    https://www.cnblogs.com/menlsh/

    https://blog.csdn.net/a200710716/article/details/51644421

  • 相关阅读:
    nginx反向代理前后端分离项目(后端多台)
    部署http访问SVN模式出现403问题
    The server quit without updating PID file
    guns开源项目数据库切换为oracle
    window环境下修改postgrep密码
    mybatis中怎样使用having?
    PostgreSQL时间段查询
    Java实现产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复。
    Jenkins构建maven项目跳过测试用例的命令
    supervisord
  • 原文地址:https://www.cnblogs.com/lesten/p/8922706.html
Copyright © 2020-2023  润新知