Complete with file compression zlib

Want to merge several files into a single compressed file, the first thought is the open source zlib library

1, download zlib

Official website: https://www.zlib.net/

In fact, the use of which formats can I choose here is the zip format, extract after download

 

2, compiled zlib library

Because I'm using windows system, so look for content under vstudio. After unpacking in . \ Zlib-1.2.11 \ contrib \ vstudio \ see under

Vc corresponding to different versions. Select a latest version, found in vc14 in zlibvc.sln, double-click to open

Because I use vs 2017 version, this problem will be prompted, click Cancel on it

zlibvc project under which reads as follows:

In which the compiler zlibvc can generate the zlib library lib and dll libraries, other project relies zlibvc.

minizip is an example zlib compression file, miniunz is unzipped the sample.

All direct easy way to generate, but generates a failure, the error message is as follows:

Error path to find bld_md64.bat , right-editor to view the contents:

ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
ml64.exe /Flgvmat64 /c /Zi gvmat64.asm

 

Input ml64.exe, output in cmd

'ml64.exe' is not an internal or external command, operable program
or batch file.

Meaning ml64.exe not find with everything and really look to find ml64.exe

The bat file ml64.exe into absolute path

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\ml64.exe" /Flinffasx64 /c /Zi inffasx64.asm
"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\ml64.exe" /Flgvmat64 /c /Zi gvmat64.asm

 

为了保留案发现场把文件另存为一个新的文件,起名为bld_ml64_2.bat

回到zlibvc.sln,右键zlibvc,点击属性-生成事件-预先生成事件,编辑命令行:

cd ..\..\masmx64

bld_ml64_2.bat

保存,重新编译,成功

 

3、学习minizip的使用过程

全部生成也可以生成minizip,这时候就可以通过debug学习minizip的使用过程了。

用到的几个主要函数如下:

zipOpen2_64        用于创建一个新的zip文件

zipOpenNewFileInZip3_64  用于在zip文件中添加新文件
zipCloseFileInZip      关闭zip文件中的新文件
zipClose          关闭zip文件
 

4、封装一下

根据minizip.c中的内容,可以压缩文件,但是在自己的项目中想要添加一个封装文件的功能还是很繁琐,所以特意将minizip.c中的main函数封装一下

新建一个sln,添加include路径(zlib路径)和链接器附加依赖项(编译zlibvc生成的zlibwapi.dll,在.\zlib-1.2.11\contrib\vstudio\vc14\x64\ZlibDllDebug\目录下)

新建FileZipper.hpp和FileZipper.cpp

FileZipper.hpp

#ifndef FILEZIPPER_HPP
#define FILEZIPPER_HPP

#include <vector>
#include <string>


#include "contrib/minizip/zip.h"
#include "contrib/minizip/iowin32.h"

#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)

class CFileZipper
{
public:
    CFileZipper();
    ~CFileZipper();

    int ZipFiles(std::string &zipFileName, std::vector<std::string> files, bool bAppendFile = false, int nCompressLevel = 0);

private:
    int isLargeFile(std::string filename);

    //char *f;                /* name of file to get info on */
    //tm_zip *tmzip;             /* return value: access, modific. and creation times */
    //uLong *dt;             /* dostime */
    uLong filetime(const char* f, tm_zip *tmzip, uLong *dt);

};
    


#endif

 

FileZipper.cpp

#include "pch.h"
#include "FileZipper.hpp"

CFileZipper::CFileZipper()
{

}

CFileZipper::~CFileZipper()
{

}

int CFileZipper::isLargeFile(std::string filename)
{
    int largeFile = 0;
    ZPOS64_T pos = 0;
    FILE* pFile = NULL;
    //pFile = fopen64(filename.c_str(), "rb");
    fopen_s(&pFile, filename.c_str(), "rb");

    if (pFile != NULL)
    {
        int n = fseeko64(pFile, 0, SEEK_END);
        pos = ftello64(pFile);

        printf("File : %s is %lld bytes\n", filename.c_str(), pos);

        if (pos >= 0xffffffff)
            largeFile = 1;

        fclose(pFile);
    }

    return largeFile;
}

uLong CFileZipper::filetime(const char* f, tm_zip *tmzip, uLong *dt)
{
    int ret = 0;
    {
        FILETIME ftLocal;
        HANDLE hFind;
        WIN32_FIND_DATAA ff32;

        hFind = FindFirstFileA(f, &ff32);
        if (hFind != INVALID_HANDLE_VALUE)
        {
            FileTimeToLocalFileTime(&(ff32.ftLastWriteTime), &ftLocal);
            FileTimeToDosDateTime(&ftLocal, ((LPWORD)dt) + 1, ((LPWORD)dt) + 0);
            FindClose(hFind);
            ret = 1;
        }
}
    return ret;
}

int CFileZipper::ZipFiles(std::string &zipFileName, std::vector<std::string> files, bool bAppendFile, int nCompressLevel)
{
    int size_buf = WRITEBUFFERSIZE;
    void* buf = NULL;
    buf = (void*)malloc(size_buf);

    if (buf == NULL)
    {
        printf("Error allocating memory\n");
        return ZIP_INTERNALERROR;
    }

    zipFile zf;
    int err, errclose;
    zlib_filefunc64_def ffunc;
    fill_win32_filefunc64A(&ffunc);
    zf = zipOpen2_64(zipFileName.c_str(), (bAppendFile) ? 2 : 0, NULL, &ffunc);

    if (zf == NULL)
    {
        printf("error opening %s\n", zipFileName.c_str());
        err = ZIP_ERRNO;
    }
    else
    {
        printf("creating %s\n", zipFileName.c_str());
        err = ZIP_OK;
    }

    int i = 0;
    for (; i < files.size() && (err == ZIP_OK); i++)
    {
        FILE* fin = NULL;
        int size_read;
        std::string filenameinzip = files[i];
        std::string savefilenameinzip;
        zip_fileinfo zi;
        unsigned long crcFile = 0;
        int zip64 = 0;

        zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
            zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
        zi.dosDate = 0;
        zi.internal_fa = 0;
        zi.external_fa = 0;
        filetime(filenameinzip.c_str(), &zi.tmz_date, &zi.dosDate);

        zip64 = isLargeFile(filenameinzip);

        savefilenameinzip = filenameinzip.substr((filenameinzip.rfind('\\') + 1));

        err = zipOpenNewFileInZip3_64(zf, savefilenameinzip.c_str(), &zi,
            NULL, 0, NULL, 0, NULL /* comment*/,
            (nCompressLevel != 0) ? Z_DEFLATED : 0,
            nCompressLevel, 0,
            /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
            -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
            NULL, crcFile, zip64);

        if (err != ZIP_OK)
            printf("error in opening %s in zipfile\n", filenameinzip.c_str());
        else
        {
            //fin = fopen64(filenameinzip.c_str(), "rb");
            fopen_s(&fin, filenameinzip.c_str(), "rb");
            if (fin == NULL)
            {
                err = ZIP_ERRNO;
                printf("error in opening %s for reading\n", filenameinzip.c_str());
            }
        }

        if (err == ZIP_OK)
        {
            do
            {
                err = ZIP_OK;
                size_read = (int)fread(buf, 1, size_buf, fin);
                if (size_read < size_buf)
                    if (feof(fin) == 0)
                    {
                        printf("error in reading %s\n", filenameinzip.c_str());
                        err = ZIP_ERRNO;
                    }

                if (size_read > 0)
                {
                    err = zipWriteInFileInZip(zf, buf, size_read);
                    if (err < 0)
                    {
                        printf("error in writing %s in the zipfile\n",
                            filenameinzip.c_str());
                    }

                }
            } while ((err == ZIP_OK) && (size_read > 0));
        }

        if (fin)
            fclose(fin);

        if (err < 0)
            err = ZIP_ERRNO;
        else
        {
            err = zipCloseFileInZip(zf);
            if (err != ZIP_OK)
                printf("error in closing %s in the zipfile\n",
                    filenameinzip.c_str());
        }
    }

    errclose = zipClose(zf, NULL);
    if (errclose != ZIP_OK)
        printf("error in closing %s\n", zipFileName.c_str());

    if (buf != NULL)
        free(buf);

    return err;
}

 

zlibTest.cpp

#include "pch.h"
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>

#include "FileZipper.hpp"

int main()
{
    std::vector<std::string> files;
    files.push_back(std::string("D:\\test\\zlibTest\\1.txt"));
    files.push_back(std::string("D:\\test\\zlibTest\\2.txt"));
    files.push_back(std::string("D:\\test\\zlibTest\\3.txt"));

    std::string zipfileName(std::string("D:\\test\\zlibTest\\123.zip"));
    CFileZipper aZipper;
    aZipper.ZipFiles(zipfileName, files);

    return 0;

}

 

运行,在D:\test\zlibTest\目录下生成了123.zip,解压到另一目录,用BCompare对比源文件,完 全 一 致

注意的是,123.zip的大小与1.txt和2.txt和3.txt这3个文件加起来一样,是因为默认的压缩等级为0,代表仅打包(在minizip.c中有提示),如果想完成压缩效果可以设置压缩等级,一般为8(minizip.c中的默认压缩等级为8)

Guess you like

Origin www.cnblogs.com/Sseakompp/p/12133869.html