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格式:

 

 

Offset Bytes Contents Descriptor
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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM