欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++ Zlib庫封裝MyZip壓縮類的詳細(xì)過程

 更新時間:2023年11月29日 16:29:01   作者:微軟技術(shù)分享  
在軟件開發(fā)中,文件的壓縮和解壓縮是一項(xiàng)常見的任務(wù),而ZIP是一種被廣泛應(yīng)用的壓縮格式,本文將聚焦于一個簡化的C++實(shí)現(xiàn),通過分析代碼,我們將深入了解其設(shè)計和實(shí)現(xiàn)細(xì)節(jié),感興趣的朋友一起看看吧

Zlib是一個開源的數(shù)據(jù)壓縮庫,提供了一種通用的數(shù)據(jù)壓縮和解壓縮算法。它最初由Jean-Loup Gailly和Mark Adler開發(fā),旨在成為一個高效、輕量級的壓縮庫,其被廣泛應(yīng)用于許多領(lǐng)域,包括網(wǎng)絡(luò)通信、文件壓縮、數(shù)據(jù)庫系統(tǒng)等。其壓縮算法是基于DEFLATE算法,這是一種無損數(shù)據(jù)壓縮算法,通常能夠提供相當(dāng)高的壓縮比。

在軟件開發(fā)中,文件的壓縮和解壓縮是一項(xiàng)常見的任務(wù),而ZIP是一種被廣泛應(yīng)用的壓縮格式。為了方便地處理ZIP壓縮和解壓縮操作,開發(fā)者通常使用各種編程語言和庫來實(shí)現(xiàn)這些功能。本文將聚焦于一個簡化的C++實(shí)現(xiàn),通過分析代碼,我們將深入了解其設(shè)計和實(shí)現(xiàn)細(xì)節(jié)。

類的功能實(shí)現(xiàn)

MyZip類旨在提供簡單易用的ZIP壓縮和解壓縮功能。通過成員函數(shù)CompressUnCompress,該類使得對目錄的ZIP壓縮和ZIP文件的解壓變得相對容易。

ZIP壓縮函數(shù) Compress

Compress函數(shù)通過zlib庫提供的ZIP壓縮功能,遞歸地將目錄下的文件添加到ZIP文件中。其中,nyCollectfileInDirtoZip函數(shù)負(fù)責(zé)遍歷目錄,而nyAddfiletoZip函數(shù)則用于添加文件到ZIP中。這種設(shè)計使得代碼模塊化,易于理解。

ZIP解壓函數(shù) UnCompress

UnCompress函數(shù)通過zlib庫提供的ZIP解壓功能,將ZIP文件解壓到指定目錄。函數(shù)中使用了unz系列函數(shù)來遍歷ZIP文件中的文件信息,并根據(jù)文件類型進(jìn)行相應(yīng)的處理。這包括創(chuàng)建目錄和寫入文件,使得解壓后的目錄結(jié)構(gòu)與ZIP文件一致。

將如上的壓縮與解壓方法封裝成MyZip類,調(diào)用zip.Compress()實(shí)現(xiàn)壓縮目錄,調(diào)用zip.UnCompress()則實(shí)現(xiàn)解壓縮目錄。這些函數(shù)使用了zlib庫的ZIP壓縮和解壓縮功能,并可以在項(xiàng)目中被應(yīng)用,該類代碼如下所示;

#define ZLIB_WINAPI
#include <string>
#include <iostream>
#include <vector>
#include <Shlwapi.h> 
#include <zip.h>
#include <unzip.h>
#include <zlib.h>
using namespace std;
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "zlibstat.lib")
class MyZip
{
private:
  // 向ZIP文件中添加文件
  bool nyAddfiletoZip(zipFile zfile, const std::string& fileNameinZip, const std::string& srcfile)
  {
    if (NULL == zfile || fileNameinZip.empty())
    {
      return false;
    }
    int nErr = 0;
    zip_fileinfo zinfo = { 0 };
    tm_zip tmz = { 0 };
    zinfo.tmz_date = tmz;
    zinfo.dosDate = 0;
    zinfo.internal_fa = 0;
    zinfo.external_fa = 0;
    // 構(gòu)建新文件名
    char sznewfileName[MAX_PATH] = { 0 };
    memset(sznewfileName, 0x00, sizeof(sznewfileName));
    strcat_s(sznewfileName, fileNameinZip.c_str());
    if (srcfile.empty())
    {
      strcat_s(sznewfileName, "\\");
    }
    // 在ZIP中打開新文件
    nErr = zipOpenNewFileInZip(zfile, sznewfileName, &zinfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
    if (nErr != ZIP_OK)
    {
      return false;
    }
    // 如果有源文件,讀取并寫入ZIP文件
    if (!srcfile.empty())
    {
      FILE* srcfp = _fsopen(srcfile.c_str(), "rb", _SH_DENYNO);
      if (NULL == srcfp)
      {
        return false;
      }
      int numBytes = 0;
      char* pBuf = new char[1024 * 100];
      if (NULL == pBuf)
      {
        return false;
      }
      // 逐塊讀取源文件并寫入ZIP
      while (!feof(srcfp))
      {
        memset(pBuf, 0x00, sizeof(pBuf));
        numBytes = fread(pBuf, 1, sizeof(pBuf), srcfp);
        nErr = zipWriteInFileInZip(zfile, pBuf, numBytes);
        if (ferror(srcfp))
        {
          break;
        }
      }
      delete[] pBuf;
      fclose(srcfp);
    }
    // 關(guān)閉ZIP文件中的當(dāng)前文件
    zipCloseFileInZip(zfile);
    return true;
  }
  // 遞歸地將目錄下的文件添加到ZIP
  bool nyCollectfileInDirtoZip(zipFile zfile, const std::string& filepath, const std::string& parentdirName)
  {
    if (NULL == zfile || filepath.empty())
    {
      return false;
    }
    bool bFile = false;
    std::string relativepath = "";
    WIN32_FIND_DATAA findFileData;
    char szpath[MAX_PATH] = { 0 };
    if (::PathIsDirectoryA(filepath.c_str()))
    {
      strcpy_s(szpath, sizeof(szpath) / sizeof(szpath[0]), filepath.c_str());
      int len = strlen(szpath) + strlen("\\*.*") + 1;
      strcat_s(szpath, len, "\\*.*");
    }
    else
    {
      bFile = true;
      strcpy_s(szpath, sizeof(szpath) / sizeof(szpath[0]), filepath.c_str());
    }
    HANDLE hFile = ::FindFirstFileA(szpath, &findFileData);
    if (NULL == hFile)
    {
      return false;
    }
    do
    {
      // 構(gòu)建相對路徑
      if (parentdirName.empty())
        relativepath = findFileData.cFileName;
      else
        relativepath = parentdirName + "\\" + findFileData.cFileName;
      // 如果是目錄,遞歸處理子目錄
      if (findFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
      {
        if (strcmp(findFileData.cFileName, ".") != 0 && strcmp(findFileData.cFileName, "..") != 0)
        {
          nyAddfiletoZip(zfile, relativepath, "");
          char szTemp[MAX_PATH] = { 0 };
          strcpy_s(szTemp, filepath.c_str());
          strcat_s(szTemp, "\\");
          strcat_s(szTemp, findFileData.cFileName);
          nyCollectfileInDirtoZip(zfile, szTemp, relativepath);
        }
        continue;
      }
      char szTemp[MAX_PATH] = { 0 };
      if (bFile)
      {
        strcpy_s(szTemp, filepath.c_str());
      }
      else
      {
        strcpy_s(szTemp, filepath.c_str());
        strcat_s(szTemp, "\\");
        strcat_s(szTemp, findFileData.cFileName);
      }
      // 將文件添加到ZIP
      nyAddfiletoZip(zfile, relativepath, szTemp);
    } while (::FindNextFileA(hFile, &findFileData));
    FindClose(hFile);
    return true;
  }
  // 替換字符串中的所有指定子串
  std::string& replace_all(std::string& str, const std::string& old_value, const std::string& new_value)
  {
    while (true)
    {
      std::string::size_type pos(0);
      if ((pos = str.find(old_value)) != std::string::npos)
        str.replace(pos, old_value.length(), new_value);
      else
        break;
    }
    return str;
  }
  // 創(chuàng)建多級目錄
  BOOL CreatedMultipleDirectory(const std::string& direct)
  {
    std::string Directoryname = direct;
    if (Directoryname[Directoryname.length() - 1] != '\\')
    {
      Directoryname.append(1, '\\');
    }
    std::vector< std::string> vpath;
    std::string strtemp;
    BOOL  bSuccess = FALSE;
    // 遍歷目錄字符串,逐級創(chuàng)建目錄
    for (int i = 0; i < Directoryname.length(); i++)
    {
      if (Directoryname[i] != '\\')
      {
        strtemp.append(1, Directoryname[i]);
      }
      else
      {
        vpath.push_back(strtemp);
        strtemp.append(1, '\\');
      }
    }
    std::vector< std::string>::iterator vIter = vpath.begin();
    for (; vIter != vpath.end(); vIter++)
    {
      bSuccess = CreateDirectoryA(vIter->c_str(), NULL) ? TRUE : FALSE;
    }
    return bSuccess;
  }
public:
  // 壓縮目錄
  bool Compress(const std::string& dirpathName, const std::string& zipfileName, const std::string& parentdirName)
  {
    bool bRet = false;
    zipFile zFile = NULL;
    // 根據(jù)ZIP文件是否存在選擇打開方式
    if (!::PathFileExistsA(zipfileName.c_str()))
    {
      zFile = zipOpen(zipfileName.c_str(), APPEND_STATUS_CREATE);
    }
    else
    {
      zFile = zipOpen(zipfileName.c_str(), APPEND_STATUS_ADDINZIP);
    }
    if (NULL == zFile)
    {
      return bRet;
    }
    // 將目錄下的文件添加到ZIP
    if (nyCollectfileInDirtoZip(zFile, dirpathName, parentdirName))
    {
      bRet = true;
    }
    zipClose(zFile, NULL);
    return bRet;
  }
  // 解壓目錄
  bool UnCompress(const std::string& strFilePath, const std::string& strTempPath)
  {
    int nReturnValue;
    string tempFilePath;
    string srcFilePath(strFilePath);
    string destFilePath;
    // 打開ZIP文件
    unzFile unzfile = unzOpen(srcFilePath.c_str());
    if (unzfile == NULL)
    {
      return false;
    }
    unz_global_info* pGlobalInfo = new unz_global_info;
    nReturnValue = unzGetGlobalInfo(unzfile, pGlobalInfo);
    if (nReturnValue != UNZ_OK)
    {
      return false;
    }
    unz_file_info* pFileInfo = new unz_file_info;
    char szZipFName[MAX_PATH] = { 0 };
    char szExtraName[MAX_PATH] = { 0 };
    char szCommName[MAX_PATH] = { 0 };
    for (int i = 0; i < pGlobalInfo->number_entry; i++)
    {
      nReturnValue = unzGetCurrentFileInfo(unzfile, pFileInfo, szZipFName, MAX_PATH, szExtraName, MAX_PATH, szCommName, MAX_PATH);
      if (nReturnValue != UNZ_OK)
        return false;
      string strZipFName = szZipFName;
      // 如果是目錄,創(chuàng)建相應(yīng)目錄
      if (pFileInfo->external_fa == FILE_ATTRIBUTE_DIRECTORY || (strZipFName.rfind('/') == strZipFName.length() - 1))
      {
        destFilePath = strTempPath + "http://" + szZipFName;
        CreateDirectoryA(destFilePath.c_str(), NULL);
      }
      else
      {
        string strFullFilePath;
        tempFilePath = strTempPath + "/" + szZipFName;
        strFullFilePath = tempFilePath;
        int nPos = tempFilePath.rfind("/");
        int nPosRev = tempFilePath.rfind("\\");
        if (nPosRev == string::npos && nPos == string::npos)
          continue;
        size_t nSplitPos = nPos > nPosRev ? nPos : nPosRev;
        destFilePath = tempFilePath.substr(0, nSplitPos + 1);
        // 創(chuàng)建多級目錄
        if (!PathIsDirectoryA(destFilePath.c_str()))
        {
          destFilePath = replace_all(destFilePath, "/", "\\");
          int bRet = CreatedMultipleDirectory(destFilePath);
        }
        strFullFilePath = replace_all(strFullFilePath, "/", "\\");
        // 創(chuàng)建文件并寫入數(shù)據(jù)
        HANDLE hFile = CreateFileA(strFullFilePath.c_str(), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
        if (hFile == INVALID_HANDLE_VALUE)
        {
          return false;
        }
        nReturnValue = unzOpenCurrentFile(unzfile);
        if (nReturnValue != UNZ_OK)
        {
          CloseHandle(hFile);
          return false;
        }
        uLong BUFFER_SIZE = pFileInfo->uncompressed_size;
        void* szReadBuffer = NULL;
        szReadBuffer = (char*)malloc(BUFFER_SIZE);
        if (NULL == szReadBuffer)
        {
          break;
        }
        // 逐塊讀取ZIP文件并寫入目標(biāo)文件
        while (TRUE)
        {
          memset(szReadBuffer, 0, BUFFER_SIZE);
          int nReadFileSize = 0;
          nReadFileSize = unzReadCurrentFile(unzfile, szReadBuffer, BUFFER_SIZE);
          if (nReadFileSize < 0)
          {
            unzCloseCurrentFile(unzfile);
            CloseHandle(hFile);
            return false;
          }
          else if (nReadFileSize == 0)
          {
            unzCloseCurrentFile(unzfile);
            CloseHandle(hFile);
            break;
          }
          else
          {
            DWORD dWrite = 0;
            BOOL bWriteSuccessed = WriteFile(hFile, szReadBuffer, BUFFER_SIZE, &dWrite, NULL);
            if (!bWriteSuccessed)
            {
              unzCloseCurrentFile(unzfile);
              CloseHandle(hFile);
              return false;
            }
          }
        }
        free(szReadBuffer);
      }
      unzGoToNextFile(unzfile);
    }
    delete pFileInfo;
    delete pGlobalInfo;
    if (unzfile)
    {
      unzClose(unzfile);
    }
    return true;
  }
};

如何使用類

壓縮文件時可以通過調(diào)用zip.Compress()函數(shù)實(shí)現(xiàn),該函數(shù)接受3個參數(shù),第一個參數(shù)是需要壓縮的目錄名,第二個參數(shù)是壓縮后保存的文件名,第三個參數(shù)則是壓縮后主目錄的名字,我們以壓縮D:\\csdn目錄下的所有文件為例,代碼如下所示;

int main(int argc, char* argv[])
{
	MyZip zip;
	// 壓縮目錄
	std::string compress_src = "D:\\csdn";                               // 壓縮目錄
	std::string compress_dst = "D:\\test.zip";                           // 壓縮后
	bool compress_flag = zip.Compress(compress_src, compress_dst, "lyshark");
	std::cout << "壓縮狀態(tài): " << compress_flag << std::endl;
	system("pause");
	return 0;
}

壓縮后可以看到對應(yīng)的壓縮包內(nèi)容,如下所示;

解壓縮與壓縮類似,通過調(diào)用zip.UnCompress實(shí)現(xiàn),該方法需要傳入兩個參數(shù),被壓縮的文件名和解壓到的目錄名,如果目錄不存在則會創(chuàng)建并解壓。

int main(int argc, char* argv[])
{
	MyZip zip;
	// 解壓縮目錄
	std::string uncompress_src = "D:\\test.zip";                      // 被解壓文件
	std::string uncompress_dst = "D:\\dst";                           // 解壓到
	bool compress_flag = zip.UnCompress(uncompress_src, uncompress_dst);
	std::cout << "解壓縮狀態(tài): " << compress_flag << std::endl;
	system("pause");
	return 0;
}

輸出效果如下所示;

到此這篇關(guān)于C/C++ Zlib庫封裝MyZip壓縮類的文章就介紹到這了,更多相關(guān)C++封裝Zlib庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Qt QDir路徑類及使用方法

    Qt QDir路徑類及使用方法

    QDir是Qt中用于操作文件系統(tǒng)目錄的類,提供了多種方法來管理和查詢目錄,如設(shè)置當(dāng)前目錄、列舉文件和子目錄、創(chuàng)建和刪除目錄等,它支持基于字符串路徑的操作,并且可以使用過濾器和排序功能,通過示例代碼,展示了如何使用QDir進(jìn)行各種目錄操作,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • C++11-20 常量表達(dá)式的使用

    C++11-20 常量表達(dá)式的使用

    本文主要介紹了C++11-20常量表達(dá)式,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言實(shí)現(xiàn)合并字符串

    C語言實(shí)現(xiàn)合并字符串

    今天小編就為大家分享一篇C語言實(shí)現(xiàn)合并字符串,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • C++?Date類的具體使用(構(gòu)建,重載等)

    C++?Date類的具體使用(構(gòu)建,重載等)

    本文主要介紹了C++?Date類的具體使用(構(gòu)建,重載等),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • C++中命名空間的概念及使用詳解

    C++中命名空間的概念及使用詳解

    這篇文章主要介紹了C++中命名空間的概念及使用詳解,使用命名空間的目的是對標(biāo)識符的名稱進(jìn)行本地化,以避免命名沖突或名字污染,namespace關(guān)鍵字就是針對這種問題而出現(xiàn)的,需要的朋友可以參考下
    2023-08-08
  • C語言用fstat函數(shù)獲取文件的大小方法

    C語言用fstat函數(shù)獲取文件的大小方法

    今天小編就為大家分享一篇關(guān)于C語言用fstat函數(shù)獲取文件的大小方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 一文詳解C++的訪問說明符

    一文詳解C++的訪問說明符

    訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關(guān)鍵字,它們用于封裝類數(shù)據(jù)并保護(hù)其免受意外修改或?yàn)E用,本文將給大家詳細(xì)的介紹一下C++的訪問說明符,感興趣的朋友可以參考下
    2024-04-04
  • C語言中g(shù)etchar()與putchar()函數(shù)詳解

    C語言中g(shù)etchar()與putchar()函數(shù)詳解

    本文主要介紹了C語言中g(shù)etchar()與putchar()函數(shù)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • OpenCV中的cv::Mat函數(shù)將數(shù)據(jù)寫入txt文件

    OpenCV中的cv::Mat函數(shù)將數(shù)據(jù)寫入txt文件

    這篇文章主要介紹了OpenCVcv::Mat中的數(shù)據(jù)按行列寫入txt文件中,需要的朋友可以參考下
    2018-05-05
  • C語言實(shí)現(xiàn)航班管理系統(tǒng)

    C語言實(shí)現(xiàn)航班管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)航班管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12

最新評論