zlib库使用

编译

下载http://www.zlib.net 下载最新版本1.2.11

Linux
解压: tar -xvf zlib-1.2.11.tar.gz
配置路径

./configure --prefix=/develop/zlib-1.2.11-lib/
make
make install

Windows
解压后,进入vs工程目录zlib-1.2.11\contrib\vstudio

打开了vs10工程编译相应的版本,zlibstat是静态版本,zlibvc为动态版本。

注意:widows导入zlib库时需要预编译两个宏
#ZLIB_WINAPI:表示zlib使用win的api
#Z_SOLO:表示把zlib库编译成单独的不依赖第三方的库,比如Linux的api,在我window上编译器时必须定义这个宏
DEFINES += ZLIB_WINAPI Z_SOLO
#ZLIB_WINAPI:表示zlib使用win的api
#Z_SOLO:表示把zlib库编译成单独的不依赖第三方的库,比如Linux的api,在我window上编译器时必须定义这个宏
DEFINES += ZLIB_WINAPI Z_SOLO

为了导入minizip工程(压缩文件夹),必须导入以下文件:

                LIBS += -L$$PWD/zlib_1_2_11/lib -lzlibwapi

                INCLUDEPATH += $$PWD/zlib_1_2_11/include
                HEADERS += $$PWD/zlib_1_2_11/include/zconf.h \
                           $$PWD/zlib_1_2_11/include/zlib.h \
                           $$PWD/zlib_1_2_11/include/zip.h \
                           $$PWD/zlib_1_2_11/include/unzip.h \
                           $$PWD/zlib_1_2_11/include/ioapi.h \
                           $$PWD/zlib_1_2_11/include/iowin32.h \

此时编译,如果发现还是报错,原因是因为minizip中没有添加上,zlib.dll库的头文件,导致无法调用zlib.dll的接口。
解决方法:在zip.h中添加头文件

#include "zconf.h"
#include "zlib.h"

解析

zlib.h

zlib.h-对数据进行压缩(一般是对单个文件)
(1)int compress (Bytef *dest,   uLongf *destLen, const Bytef *source, uLong sourceLen);
把源缓冲压缩成目的缓冲, 就那么简单, 一个函数搞定.
参数:
source:输入字符串,要求以'\ 0'结尾,sourceLen = strlen(source)
dest:输出字符串,预先分配的空间,在源很短,只有几个字节时,长度需要比源长12个字节,一般情况,可以比较短。一般的压缩率是2〜5。
返回值:
如果成功,则返回值compress返回Z_OK,
如果没有足够的内存,则返回Z_MEM_ERROR,
如果输出缓冲区中的空间不足,则返回Z_BUF_ERROR 。
zlib.h:
#定义Z_OK 0
#定义Z_STREAM_END 1
#定义Z_NEED_DICT 2
#定义Z_ERRNO(-1)
#定义Z_STREAM_ERROR(-2)
#定义Z_DATA_ERROR(-3)
#定义Z_MEM_ERROR(-4)
#定义Z_BUF_ERROR(-5 )
#定义Z_VERSION_ERROR(-6)

(2) int compress2 (Bytef *dest,   uLongf *destLen,const Bytef *source, uLong sourceLen,int level);
功能和上一个函数一样,都一个参数可以指定压缩质量和压缩数度之间的关系(0-9)不敢肯定这个参数的话不用太在意它,明白一个道理就好了:要想得到高的压缩比就要多花时间

(3) uLong compressBound (uLong sourceLen);
计算需要的缓冲区长度. 假设你在压缩之前就想知道你的产度为sourcelen 的数据压缩后有多大, 可调用这个函数计算一下,这个函数并不能得到精确的结果,但是它可以保证实际输出长度肯定小于它计算出来的长度

(4) int uncompress (Bytef *dest,   uLongf *destLen,const Bytef *source, uLong sourceLen);
解压缩(看名字就知道了:),统一解压缩函数,注意传出串的长度
返回值:
如果成功,uncompress返回Z_OK,如果没有足够的内存,则返回Z_MEM_ERROR,
如果输出缓冲区中没有足够的空间,则返回Z_BUF_ERROR,
或者如果输入数据已损坏或不完整,则Z_DATA_ERROR

(5) deflateInit() + deflate() + deflateEnd()
3个函数结合使用完成压缩功能,具体用法看 example.c 的test_deflate()函数. 其实 compress() 函数内部就是用这3个函数实现的(工程 zlib 的 compress.c 文件)

(6) inflateInit() + inflate() + inflateEnd()
和(5)类似,完成解压缩功能.

(7) gz开头的函数. 用来操作*.gz的文件,和文件stdio调用方式类似.想知道怎么用的话看example.c 的 test_gzio() 函数,很easy.

(8) 其他诸如获得版本等函数就不说了.
总结: 其实只要有了compress() 和uncompress() 两个函数,在大多数应用中就足够了.

权限设置方法:
1。修改zlib.h的值
2。编译时指定
   -DMAX_WBITS = 15 -DMAX_MEM_LEVEL = 8(
   数值)DMAX_WBITS,窗口尺寸,15看起来是最大的了,再高会出错。这个值是最好的。
   DMAX_MEM_LEVEL最大是8的小话将会对性能有负面影响

 minizip概述

zipFile zipOpen (const char *pathname,int append);
根据传入的文件路径,打开/创建一个zipFile文件。
关于其参数:
①   const char *pathname:需要打开/创建的压缩文件路径,比如F:/dump.zip
②   int append:参数,其取值有以下三种:
    // APPEND_STATUS_CREATE              不存在就创建,存在就截断(清空)
    // APPEND_STATUS_ADDINZIP            不存在打开失败,存在就追加(原本压缩包中的内容不清空)
    // APPEND_STATUS_CREATEAFTER  不存在打开失败,存在就截断(清空)

int zipOpenNewFileInZip3_64(    zipFile file,                     // zip文件,路径比如F:/dump.zip
    //注意,filename需要输入一个相对路径。即认为zip文件开始压缩的第一级目录为根目录,所有的子文件及子文件夹的路径都输入相对于该根目录的路径.若传入的相对路径有多级目录,那么zipOpenNewFileInZip ()会自动创建这些目录。比如:MyFile/test.txt,会自动创建MyFile目录
                                const char* filename,             // zip中需要写入的子文件的文件名,结尾是否带有”/”决定了创建的是子文件还是文件夹,比如在dump.zip中写入/dir/aa.txt
                                const zip_fileinfo* zipfi,         // 传入一些包括日期在内的zip补充信息
                                const void* extrafield_local,     // 本子文件扩展信息
                                uInt size_extrafield_local,     // 本子文件扩展信息大小
                                const void* extrafield_global,     // 全局文件扩展信息
                                uInt size_extrafield_global,     // 全局文件扩展信息大小
                                const char* comment,             // 注释
                                int method,                        // 压缩方式:0-store,ZDEFLATED-deflate
                                int level,                        // 压缩等级:[0,9]。详见2中详细说明
                                int raw,                        // 若raw=1,则写原始文件
                                int windowBits,                    // 窗口大小,范围是[8,15]。值越大越好
                                int memLevel,                    // 压缩时内存分配等级。越大,压缩越快。范围是[1,9],默认为8
                                int strategy,                    // 压缩算法。详见下面说明
                                const char* password,            // 进行加密的密码
                                uLong crcForCrypting,            // crc32校验码
                                int zip64                        // 是否在文件头追加额外信息块
                            );

关于参数:
(1)int strategy:压缩算法。其取值可以为:
Z_DEFAULT_STRATEGY:常规数据
Z_FILTERED:由过滤器产生的数据
Z_HUFFMAN_ONLY:Huffman编码数据
Z_RLE:游标编码(run-length encoding)
(2)int zip64   :若设为1,则在头文件中添加额外信息。如果被压缩文件的原始大小过大,则必须设为1。所谓过大,是指size >=0xffffffff。

int zipWriteInFileInZip (zipFile file,constvoid*buf, unsigned len);
向打开的当前子文件中写入数据。
关于其参数:
zipFile file:已创建的zipFile文件
constvoid*buf:数据缓存区,被压缩文件的原始二进制数据存放在这里
unsigned len:从数据缓存区中读出的字节数

int zipCloseFileInZip (zipFile file);
关闭当前打开的子文件/文件夹

int zipClose (zipFile file,const char* global_comment);
关闭zipFile文件,压缩完成。

压缩文件

使用minizip压缩文件,我们一般使用如下的几个函数:

zipOpen2_64:新建一个空的Zip文件
zipOpenNewFileInZip3_64:添加一个文件到之前创建好的Zip文件中
zipWriteInFileInZip:读取文件内容并写入到Zip文件
zipCloseFileInZip:关闭当前Zip文件
zipClose: 关闭Zip文件

这里有几个地方需要注意:

1) 在调用zipOpenNewFileInZip3_64在Zip文件中添加文件之前,我们需要计算文件的CRC效验码和文件的时间戳信息,否则,会出现生成的Zip文件解压时头部错误的问题。

2) 读取文件并写入Zip文件过程中,我们需要使用循环的方式,每次对文件读取一定的字节,并注意检查是否到达文件尾(EOF),同时需要检查zipWriteInFileInZip调用是否失败。

伪代码如下:

新建Zip文件(zipOpen2_64)
获取源文件时间戳信息(filetime)
在Zip中创建新文件(zipOpenNewFileInZip3_64)
打开源文件(fopen)
do
{
    读取源文件一定字节(fread)
    写入到Zip文件(zipWriteInFileInZip)
} while (源文件未到达EOF)
关闭源文件(fclose)
关闭Zip当前文件(zipCloseFileInZip)
关闭Zip文件(zipClose)

解压Zip文件

在解压一个Zip文件时,我们需要使用的函数如下:

unzOpen64:打开Zip文件
unzGetGlobalInfo64:获取Zip文件的全局信息
unzGetCurrentFileInfo64:获取当前文件信息
unzOpenCurrentFile:打开Zip中的文件
unzReadCurrentFile:读取文件内容
unzCloseCurrentFile:关闭当前文件
unzGoToNextFile:准备读取Zip文件中的下一个文件
unzClose:关闭Zip文件

伪代码如下:

打开Zip文件(unzOpen64)
获取全局信息(unzGetGlobalInfo64)
for (从全局信息中获取所有Zip文件并遍历)
    获取当前文件信息(unzGetCurrentFileInfo64)
    if (当前Zip文件是目录)
        创建目录
    else
        打开Zip文件(unzOpenCurrentFile)
        打开目标文件(fopen)
        while (Zip文件读取成功)
            读取Zip文件(unzReadCurrentFile)
            写入目标文件(fwrite)
        关闭目标文件(fclose)
        关闭当前Zip文件,是文件再能关闭,目录不能关闭(unzCloseCurrentFile)
    准备处理下一个Zip文件(unzGoToNextFile)
关闭Zip文件(unzClose)

测试代码:

pro文件

win32: {
#ZLIB_WINAPI:表示zlib使用win的api
#Z_SOLO:表示把zlib库编译成单独的不依赖第三方的库,比如Linux的api,在我window上编译器时必须定义这个宏
DEFINES += ZLIB_WINAPI Z_SOLO

                # 32bit libraty
                LIBS += -L$$PWD/zlib_1_2_11/lib -lzlibwapi

                INCLUDEPATH += $$PWD/zlib_1_2_11/include
                HEADERS += $$PWD/zlib_1_2_11/include/zconf.h \
                           $$PWD/zlib_1_2_11/include/zlib.h \
                           $$PWD/zlib_1_2_11/include/zip.h \
                           $$PWD/zlib_1_2_11/include/unzip.h \
                           $$PWD/zlib_1_2_11/include/ioapi.h \
                           $$PWD/zlib_1_2_11/include/iowin32.h \
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QDebug>
//压缩头
#include "zlib_1_2_11/include/zlib.h"
#include "zip.h"
#ifdef _WIN32
    #define USEWIN32IOAPI
    #include "iowin32.h"
#endif

//解压头
#include "unzip.h"
#define WRITEBUFFERSIZE (8192)
#ifdef __APPLE__
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif

#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QFileInfo>

inline std::string ToUtf8(const QString& str)
{
    QByteArray u8 = str.toUtf8();
    return std::string(u8.data(),u8.size());
}
//------------------------------压缩begin-------------------------------------------------------
//zipPathDir:压缩的路径,strFilePathName:压缩的文件路径,
int currentfile_WriteToZip(QString zipPathDir,QString strFilePathName,zipFile zipfile)
{
    int err = 0;
    QDir dir(zipPathDir);
    QFileInfo info(strFilePathName);
    QDateTime ctime = info.created();    // 获取文件创建时间
    zip_fileinfo zipinfo;
    zipinfo.tmz_date.tm_year = ctime.date().year();
    zipinfo.tmz_date.tm_mon = ctime.date().month();
    zipinfo.tmz_date.tm_mday = ctime.date().day();
    zipinfo.tmz_date.tm_hour = ctime.time().hour();
    zipinfo.tmz_date.tm_min = ctime.time().minute();
    zipinfo.tmz_date.tm_sec = ctime.time().second();
    zipinfo.dosDate = 0;
    zipinfo.external_fa = zipinfo.internal_fa = 0;

    //压缩文件里的路径
    QString dirPath = dir.path()+"/";
    QString pathN = info.filePath().remove(dirPath);
    std::string utf8path =  ToUtf8(pathN);
    //sig_zipFileProgress(i,entrylist.size());
    // 在zip包中打开一个新文件
    err = zipOpenNewFileInZip3_64(zipfile,//压缩文件名称
        //(注意这里不是压缩文件的路径(比如F:/dump.zip),而是压缩文件(dump.zip)里的文件路径(比如dump.zip里创建路径和文件dump/aa.txt))
        utf8path.c_str(),//在zip文件中的文件路径(我这里使用UTF8,可以根据需求自己抉择,文件名可以重复)
        &zipinfo,
        NULL,
        0,
        NULL,
        0,
        NULL,
        Z_DEFLATED,
        Z_DEFAULT_COMPRESSION,
        0,
        -MAX_WBITS,
        DEF_MEM_LEVEL,
        Z_DEFAULT_STRATEGY,//压缩参数(默认参数)
        NULL,//加密参数(不加密)
        0,//crc校验值
        0); //是否为zip64

    // 在zip包中添加新文件失败
    if(err != ZIP_OK){
        qDebug()<<"zipOpenNewFileInZip3_64 error : "<<err;
        zipCloseFileInZip(zipfile);
        return err;
    }
    QFile file(info.filePath());
    qDebug()<<"file path = "<<info.filePath();
    if(!file.open(QIODevice::ReadOnly)){
        qDebug()<<"OpenFile failed "<<info.filePath();
        zipCloseFileInZip(zipfile);
        return err;
    }


    // 读取文件内容,写入zip包文件
    qint64 filesize = file.size();
    for(qint64 rbeg = 0;rbeg<filesize;rbeg+=(4<<20)){
        QByteArray buffer = file.read(4<<20);
        err = zipWriteInFileInZip(zipfile,buffer.data(),buffer.size());//写入压缩文件
        if(err < 0){
            qDebug()<<"error : "<<err;
            break;
        }
    }
    zipCloseFileInZip(zipfile);//关闭压缩文件写入
    file.close();
    return err;
}
//递归压缩所有文件
//strDirPath递归查找文件的路径,zipPathDir压缩的文件夹,
bool zip_All_File(QString strDirPath,QString zipPathDir,zipFile zipfile)
{
    if (strDirPath.isEmpty()){
            return false;
        }
        QDir dir(strDirPath);
        if(!dir.exists()){
            return false;
        }
        dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); //设置过滤
        QFileInfoList fileList = dir.entryInfoList(); // 获取所有的文件信息
        foreach (QFileInfo file, fileList){ //遍历文件信息
            if (file.isFile()){ // 是文件
                if(currentfile_WriteToZip(zipPathDir,file.filePath(),zipfile)!=ZIP_OK)
                {
                     qDebug()<<"currentfile_WriteToZip error : "<<file.filePath();
                    return false;
                }
            }else{ // 递归
                zip_All_File(file.absoluteFilePath(),zipPathDir,zipfile);
            }
        }
        return true;
}

void zlib_archive_compress(QString path,QString outpath)
{
    QDir dir(path);
    //QStringList entrylist = FileListR(dir);

    int err = 0;
    zipFile zipfile;

#ifdef _WIN32
    zlib_filefunc64_def ffunc64;
    fill_win32_filefunc64W(&ffunc64);
//注意:如果是中文,那么QString要先转成本地编码,然后在const ushort* ushPath = QString.utf16()
    //std::wstring wpath = outpath.toStdWString();
     char cTmppath[256]={0};
     CAppHelper::UTF8ToSystem(outpathFileName,cTmppath,sizeof(cTmppath));//将outpathFileName的utf8转换成cTmppath的系统编码
     DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, cTmppath,  -1, NULL, 0);
     unsigned short *w = new unsigned short [dwNum];
     MultiByteToWideChar (CP_ACP, 0, cTmppath, -1, (LPWSTR)w,  dwNum);

    // APPEND_STATUS_CREATE              不存在就创建,存在就截断(清空)
    // APPEND_STATUS_ADDINZIP            不存在打开失败,存在就追加(原本压缩包中的内容不清空)
    // APPEND_STATUS_CREATEAFTER  不存在打开失败,存在就截断(清空)
//zipOpen2_64的第一个参数必须是是const ushort*类型
    zipfile = zipOpen2_64(wpath.c_str(),APPEND_STATUS_CREATE,NULL,&ffunc64);
#else
    zipfile = zipOpen64(ToUtf8(outpath).c_str(),APPEND_STATUS_CREATE);
#endif
    if(zipfile == NULL){
        qDebug()<<"zipOpen64 error " << ZIP_ERRNO;
        return;
    }

    zip_All_File(path,path,zipfile);//递归压缩路径下的文件

    err = zipClose(zipfile,NULL);
    if(err < 0){
        qDebug()<<"error : "<<err;
    }
}
//---------------------------------------压缩end---------------------------------------------------
//----------------------------------------解压begin-------------------------------------------------
/* change_file_date : change the date/time of a file
    filename : the filename of the file where date/time must be modified
    dosdate : the new date at the MSDos format (4 bytes)
    tmu_date : the SAME new date at the tm_unz format */
void change_file_date(
    const char *filename,
    uLong dosdate,
    tm_unz tmu_date)
{
#ifdef _WIN32
  HANDLE hFile;
  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;

  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
                      0,NULL,OPEN_EXISTING,0,NULL);
  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
  LocalFileTimeToFileTime(&ftLocal,&ftm);
  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
  CloseHandle(hFile);
#else
#ifdef unix || __APPLE__
  struct utimbuf ut;
  struct tm newdate;
  newdate.tm_sec = tmu_date.tm_sec;
  newdate.tm_min=tmu_date.tm_min;
  newdate.tm_hour=tmu_date.tm_hour;
  newdate.tm_mday=tmu_date.tm_mday;
  newdate.tm_mon=tmu_date.tm_mon;
  if (tmu_date.tm_year > 1900)
      newdate.tm_year=tmu_date.tm_year - 1900;
  else
      newdate.tm_year=tmu_date.tm_year ;
  newdate.tm_isdst=-1;

  ut.actime=ut.modtime=mktime(&newdate);
  utime(filename,&ut);
#endif
#endif
}
int currentfile_Write(unzFile uf, const char* password/*加密密码*/,QString outPath/*解压路径*/,bool bIsOrNotOverwrite /*询问是否覆盖文件*/,bool bIsCreatePath/*是否创建路径*/)
{
    FILE* fout=NULL;
    unz_file_info64 file_info;
    QString cFullFileName;//全名称
    char filename_inzip[256]={0};//在压缩包中的路径和文件名称
    char* filename_withoutpath;//文件名称,不包括路径
    bool skip=false;//是否跳过文件,不覆盖
    int err = UNZ_OK;//初始初始化,每次开始都是OK的
    //获取当前文件信息
    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
    qDebug()<<"unzGetCurrentFileInfo64:"<<filename_inzip;
    if (err!=UNZ_OK)
    {
        qDebug()<<"error with zipfile in unzGetCurrentFileInfo"<<err;
        return err;
    }

    char* p = filename_withoutpath = filename_inzip;
    while ((*p) != '\0')//找到文件名称
    {
        if (((*p)=='/') || ((*p)=='\\'))
            filename_withoutpath = p+1;
        p++;
    }

    char zipPath[256] = {0};
    memcpy(zipPath,filename_inzip,strlen(filename_inzip)-strlen(filename_withoutpath));
    if(!outPath.endsWith("\\") && !outPath.endsWith("/"))
    {
         outPath += "/";
    }
    cFullFileName = outPath + filename_inzip;
    outPath += zipPath;//纯路径
    if ((*filename_withoutpath)=='\0' && bIsCreatePath)//如果没有文件名称,表示是路径,创建路径
    {
        //创建空路径
        qDebug()<<"creating directory:"<<filename_inzip;
        //创建路径
        QDir dir(outPath);
        dir.mkpath(outPath);
    }
    else
    {
        const char* write_filename;
        std::string tmp = cFullFileName.toStdString();//中文有问题,要转码
        if(bIsCreatePath)//要创建路径
        {
            write_filename = tmp.c_str();
        }else{
            write_filename = filename_withoutpath;//只创建文件
        }

        err = unzOpenCurrentFilePassword(uf,password);//密码解压
        if (err!=UNZ_OK)
        {
            qDebug()<<"error with zipfile in unzOpenCurrentFilePassword\n"<<err;
        }

        //是否弹出覆盖询问?
        if(bIsOrNotOverwrite && err == UNZ_OK)
        {
            const char* write_filename = filename_inzip;
            FILE* ftestexist;
            ftestexist = FOPEN_FUNC(write_filename,"rb");
            if (ftestexist!=NULL)//文件打开成功,存在
            {
                fclose(ftestexist);
                //可以询问是否覆盖,skip=true则跳过,不覆盖
                //代码略。。。
            }
        }

        if(!skip && err == UNZ_OK)//默认不跳过,如果不跳过,覆盖文件
        {
            fout=FOPEN_FUNC(write_filename,"wb");

            if(fout == NULL)//打开失败
            {
                //创建路径再打开一次
                QDir dir(outPath);
                dir.mkpath(outPath);
                fout=FOPEN_FUNC(write_filename,"wb");
            }
            if (fout==NULL)
            {
                qDebug()<<"error opening :"<<write_filename;
            }
        }

        if (fout!=NULL)//打开成功
        {
            qDebug()<<" write_filename: "<<write_filename;
            char* buf = NULL;
            uInt size_buf;
            size_buf = 256;//WRITEBUFFERSIZE;
            qDebug()<<" write_filename2: "<<write_filename;
            buf = (char*)malloc(size_buf);//能否使用内存池技术?
            if (buf==NULL)
            {
                qDebug()<<"Error allocating memory";
                err = unzCloseCurrentFile(uf);
                if (err!=UNZ_OK)
                {
                    qDebug()<<"error with zipfile in unzCloseCurrentFile:"<<err;
                }
                return UNZ_INTERNALERROR;
            }
            do
            {
                memset(buf,0,size_buf);
                //如果读取大小太大,会导致崩溃,比如size_buf =8192,4096,1024
                err = unzReadCurrentFile(uf,buf,size_buf);//读取文件内容,返回读取到的字节数,小于读取失败,大于读取成功但未读完,等于0读取完成
                if (err<0)
                {
                    qDebug()<<"error with zipfile in unzReadCurrentFile:"<<err;
                    break;
                }
                if (err>0)//大于读取成功但未读完,写入
                {
                    if (fwrite(buf,err,1,fout)!=1)
                    {
                        qDebug()<<"error in writing extracted file:";
                        err=UNZ_ERRNO;
                        break;
                    }
                }
            }while (err>0);
            if(buf)
            {
                free(buf);
                buf = NULL;
            }
            if (fout)
            {
                fclose(fout);
            }

            if (err==0)//读取完成,更改文件时间
            {
                change_file_date(write_filename,file_info.dosDate,
                                 file_info.tmu_date);
            }
        }
        //文件需要关闭unzCloseCurrentFile,文件夹不用关闭
        err = unzCloseCurrentFile(uf);
        if (err!=UNZ_OK)
        {
            qDebug()<<"error with zipfile in unzCloseCurrentFile:"<<err;
        }
    }

    return err;
}
void zlib_archive_decompress2(QString zipPathName, QString outPath,const char* password,bool bIsOrNotOverwrite /*询问是否覆盖文件*/,bool bIsCreatePath/*是否创建路径*/)
{
    const char *zipfilename=NULL;
    unzFile uf=NULL;
    std::string tmpPath = zipPathName.toStdString();
    zipfilename = tmpPath.c_str();
#ifdef USEWIN32IOAPI
    zlib_filefunc64_def ffunc;
    fill_win32_filefunc64A(&ffunc);
    uf = unzOpen2_64(zipfilename,&ffunc);
#else
    uf = unzOpen64(zipfilename);
#endif
    if (uf==NULL)
    {
        qDebug()<<"Cannot open:"<<zipfilename;
        return;
    }
    unz_global_info64 gi;
    int err;

    err = unzGetGlobalInfo64(uf,&gi);//获取压缩包的全局信息
    if (err!=UNZ_OK)
        qDebug()<<"error with zipfile in unzGetGlobalInfo :"<<err;

    for (int i=0;i<gi.number_entry;i++)//遍历压缩包
    {
        if( currentfile_Write(uf,password,outPath,bIsOrNotOverwrite,bIsCreatePath) != UNZ_OK)
            break;
        //处理下一个文件
        if ((i+1)<gi.number_entry)
        {
            err = unzGoToNextFile(uf);
            if (err!=UNZ_OK)
            {
                qDebug()<<"error with zipfile in unzGoToNextFile:"<<err;
                break;
            }
        }
    }

    unzClose(uf);//关闭压缩包
}
//-------------------------------------------------解压end-----------------------------------------------

调用:

auto btnCompress = new QPushButton("压缩",this);
    connect(btnCompress,&QPushButton::clicked,this,[&](){
        zlib_archive_compress(
                    QString::fromLocal8Bit("F:/dump/"),
                    QString::fromLocal8Bit("F:/dump.zip"));


    });

    auto btndeCompress = new QPushButton("解压",this);
    connect(btndeCompress,&QPushButton::clicked,this,[&](){
        zlib_archive_decompress2(
                    QString::fromLocal8Bit("F:/gg/dump.zip"), QString::fromLocal8Bit("F:/QtCode/zlib"),NULL,false,true);
    });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十日十行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值