iOS 和 Android 解压zip文件

最近碰到了这么个需求:为了节省流量,在传输的时候需要使用zip文件传输,下载完成之后,在客户端解压zip文件。

解决方法:由于需要跨平台,在iOS和Android都使用,所以经过考虑决定使用zlib库来解压zip文件。

zlib github 地址 , 下载完成之后,在解压的文件中拷贝 zlib.h , zconf.h 两个头文件,在contrib --> minizip 文件夹中,拷贝其中的 unzip.h , ioapi.h , unzip.c , ioapi.c 文件,到你的工程中去, 然后include一下zlib.h 文件即可。

当前使用的zlib版本是 **1.2.8 **

zlib库使用步骤如下:

  1. 打开zip文件
  2. 获取zip文件信息
  3. 循环遍历文件,如果遇到文件夹则创建文件夹,如果遇到文件则把数据写入文件中
  • 解压zip文件核心代码如下: 需要传入一个zip文件的路径,和需要解压到的路径

int BPDecompress::BPDecompressZip(string zipFilePath, string strFolder) 
{
    // 1. open zip
    unzFile zipfile = unzOpen(zipFilePath.c_str());
    if (zipfile == NULL)
    {
        CP_LOGE("open zip failed , path = %s",zipFilePath.c_str());
        return -1;
    }
    
    // 2. get global info
    unz_global_info global_info;
    if (unzGetGlobalInfo(zipfile, &global_info)!=UNZ_OK){
        unzClose(zipfile);
        CP_LOGE("get global info failed\n");
        return -1;
    }
    
    // 3. loop files
    for (uLong i = 0; i<global_info.number_entry; ++i){
        
        unz_file_info64 file_info64;
        char filename[1024]={0};
        
        unzGetCurrentFileInfo64(zipfile, &file_info64, filename, sizeof(filename), NULL, 0, NULL, 0);
        
        const size_t filename_length = strlen(filename);
        char name[1024] = {0};
        if (filename[filename_length-1] == '/')
        {// make folder
            
            sprintf(name, "%s/%s", strFolder.c_str(), filename);
            BPCreateDir(name);
            
        }else{
            
            if (unzOpenCurrentFile(zipfile) != UNZ_OK)
            {
                unzClose(zipfile);
                CP_LOGE("open current file failed\n");
                return -1;
            }
            
            sprintf(name, "%s/%s", strFolder.c_str(), filename);
            
            if (BPWriteData(zipfile, name) < 0) {
                unzCloseCurrentFile(zipfile);
                unzClose(zipfile);
                CP_LOGE("wtite data into file failed\n");
                return -1;
            }
            // to set file time
        }
        unzCloseCurrentFile(zipfile);
        
        if ((i+1) < global_info.number_entry && unzGoToNextFile(zipfile) != UNZ_OK) {
            unzClose(zipfile);
            CP_LOGE("go to next failed\n");
            return -1;
        }
    }
    
    unzClose(zipfile);

    return 0;
}
    

其中:

CP_LOGE 为宏定义 ,可以加入自己定义的打印信息的宏

BPCreateDir 为创建文件夹的方法 , 用c语言实现即可

BPWriteData 为数据写入到文件中的方法

  • 写入数据到文件中的核心代码如下:需要传入一个unzFile 和 写入的路径

int BPDecompress::BPWriteData(unzFile &zipfile, const char *destPathName)
{
    if (destPathName == NULL) {
        CP_LOGE("name is null\n");
        return -1;
    }
    
    if ( BPCreateDir(destPathName) != 0)
    {
        CP_LOGE("[BPWriteData] create dir failed . path = %s\n",destPathName);
        return -1;
    }
    
    // 删除以.开头的文件
    string s_path = destPathName;
    int index = (int)s_path.find_last_of("/");
    string name = s_path.substr(index+1);
    if (name.find(".") == 0)  return 0;
    
    FILE *fp = fopen(destPathName, "wb");
    if (fp == NULL) {
        CP_LOGE("open file failed. destPathName = %s\n",destPathName);
        return -1;
    }
    
    char read_buffer[1024] = {0};
    int error = UNZ_OK;
    
    do {
        error = unzReadCurrentFile(zipfile, read_buffer, 1024);
        
        if (error < 0 )
        {
            CP_LOGE("[unzReadCurrentFile] error = %d\n", error);
            return -1;
        }
        
        if (error > 0) {
            fwrite(read_buffer, error, 1, fp);
        }
        
    } while (error > 0);
    
    fclose(fp);
    fp = NULL;
    
    return 0;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容