使用zlib库进行目录压缩

时间:2022-01-01 09:11:20

代码很简单,具体过程就不写了。
关于加密压缩,可以看http://www.zlib.net/zlib_faq.html#faq38 中的描述,说是不支持的,但是创建的时候可以传入密码进去,不过我还没有搞清楚这个密码要如何设置。

#include "zlib.h"
#include "zip.h"
#ifdef _WIN32
#define USEWIN32IOAPI
#include "iowin32.h"
#endif

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

/*转换Qstring到utf8字符串*/
inline std::string ToUtf8(const QString& str)
{
    QByteArray u8 = str.toUtf8();
    return std::string(u8.data(),u8.size());
}


QStringList FileListR(const QDir& dir)
{
    QFileInfoList fileinfolist = dir.entryInfoList(
                QDir::NoDotAndDotDot|QDir::Files|QDir::Dirs);
    QStringList files;
    for(int i=0;i<fileinfolist.size();++i){
        QFileInfo& info = fileinfolist[i];
        if(info.isDir()){
            files.append(FileListR(QDir(info.filePath())));
            continue;
        }
        files.append(info.filePath());
    }
    return files;
}


// zlib打包压缩测试
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);
    std::wstring wpath = outpath.toStdWString();
    zipfile = zipOpen2_64(wpath.c_str(),APPEND_STATUS_CREATE,NULL,&ffunc64);
#else
    zipfile = zipOpen64(ToUtf8(path).c_str(),APPEND_STATUS_CREATE);
#endif
    if(zipfile == NULL){
        qDebug()<<"zipOpen64 error " << ZIP_ERRNO;
        return;
    }

    // 逐个文件添加
    for(int i=0;i<entrylist.size();++i){
        QFileInfo info(entrylist[i]);
        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;
        
        // 在zip包中打开一个新文件
        err = zipOpenNewFileInZip3_64(
                    zipfile,
                    ToUtf8(info.filePath().remove(dir.path())).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()<<QString::fromAscii("zipOpenNewFileInZip3_64 failed ")<<err;
            zipCloseFileInZip(zipfile);
           break;
        }
        QFile file(info.filePath());
        if(!file.open(QIODevice::ReadOnly)){
            qDebug()<<QString::fromAscii("OpenFile failed ")<<file.fileName();
            zipCloseFileInZip(zipfile);
            continue;
        }
        // 读取文件内容,写入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);
    }

    err = zipClose(zipfile,NULL);
    if(err < 0){
        qDebug()<<"error : "<<err;
    }
}



int main(int argc, char *argv[])
{
    QTime time;
    time.start();
    zlib_archive_compress(
                QString::fromLocal8Bit("Z:/Everything-SDK/src"),
                QString::fromLocal8Bit("Z:/Everything-SDK/srctest.zip"));
    int t = time.elapsed();
    qDebug()<<t<<" ms";
    return 0;
}