最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C/C++使用Zlib實(shí)現(xiàn)文件的壓縮與解壓

 更新時(shí)間:2023年11月28日 10:34:36   作者:微軟技術(shù)分享  
zlib 是一個(gè)開源的數(shù)據(jù)壓縮庫(kù),旨在提供高效、輕量級(jí)的壓縮和解壓縮算法,本文將介紹如何使用 zlib 庫(kù)進(jìn)行數(shù)據(jù)的壓縮和解壓縮,以及如何保存和讀取壓縮后的文件,感興趣的可以了解下

在軟件開發(fā)和數(shù)據(jù)處理中,對(duì)數(shù)據(jù)進(jìn)行高效的壓縮和解壓縮是一項(xiàng)重要的任務(wù)。這不僅有助于減小數(shù)據(jù)在網(wǎng)絡(luò)傳輸和存儲(chǔ)中的占用空間,還能提高系統(tǒng)的性能和響應(yīng)速度。本文將介紹如何使用 zlib 庫(kù)進(jìn)行數(shù)據(jù)的壓縮和解壓縮,以及如何保存和讀取壓縮后的文件。zlib 是一個(gè)開源的數(shù)據(jù)壓縮庫(kù),旨在提供高效、輕量級(jí)的壓縮和解壓縮算法。其核心壓縮算法基于 DEFLATE,這是一種無損數(shù)據(jù)壓縮算法,通常能夠提供相當(dāng)高的壓縮比。zlib 庫(kù)廣泛應(yīng)用于多個(gè)領(lǐng)域,包括網(wǎng)絡(luò)通信、文件壓縮、數(shù)據(jù)庫(kù)系統(tǒng)等。

保存文件

使用 CreateFile 打開文件,通過 WriteFile 向文件中寫出數(shù)據(jù),最后調(diào)用 CloseHandle 關(guān)閉句柄,實(shí)現(xiàn)文件的保存。

#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")

BOOL SaveToFile(char *pszFileName, BYTE *pData, DWORD dwDataSize)
{
	char szSaveName[MAX_PATH] = { 0 };
	lstrcpy(szSaveName, pszFileName);

	HANDLE hFile = CreateFile(szSaveName, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
		FILE_ATTRIBUTE_ARCHIVE, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		return FALSE;
	}

	DWORD dwRet = 0;
	WriteFile(hFile, pData, dwDataSize, &dwRet, NULL);

	CloseHandle(hFile);

	return TRUE;
}

int main(int argc, char * argv[])
{
	char szBuffer[1024] = { 0 };

	strcpy(szBuffer, "test 123123");

	SaveToFile("d://test.txt", (BYTE *)szBuffer, sizeof(szBuffer));

	system("pause");
	return 0;
}

文件壓縮

compress 是 zlib 庫(kù)提供的用于數(shù)據(jù)壓縮的函數(shù),通過該函數(shù)可以將數(shù)據(jù)進(jìn)行壓縮。下面是一個(gè)示例,演示了如何使用 zlib 庫(kù)進(jìn)行文件壓縮。

它的原型如下:

int compress(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen);
  • dest:指向存放壓縮后數(shù)據(jù)的緩沖區(qū)的指針。
  • destLen:傳入時(shí)為壓縮緩沖區(qū)的大小,傳出時(shí)為實(shí)際壓縮后數(shù)據(jù)的大小。
  • source:指向待壓縮數(shù)據(jù)的緩沖區(qū)的指針。
  • sourceLen:待壓縮數(shù)據(jù)的大小。

compress 函數(shù)的作用是將 source 指向的數(shù)據(jù)進(jìn)行壓縮,并將結(jié)果存放在 dest 指向的緩沖區(qū)中。destLen 傳入時(shí)應(yīng)該是 dest 緩沖區(qū)的大小,函數(shù)執(zhí)行后,destLen 會(huì)更新為實(shí)際壓縮后數(shù)據(jù)的大小。

函數(shù)返回值為壓縮的執(zhí)行狀態(tài),可能的返回值包括:

  • Z_OK:壓縮成功。
  • Z_MEM_ERROR:內(nèi)存分配失敗。
  • Z_BUF_ERROR:壓縮輸出緩沖區(qū)不足。

這個(gè)函數(shù)實(shí)際上是使用 DEFLATE 算法進(jìn)行壓縮,DEFLATE 是一種通用的壓縮算法,也是 zlib 庫(kù)的核心算法之一。壓縮后的數(shù)據(jù)可以使用 uncompress 函數(shù)進(jìn)行解壓縮。

總體而言,compress 函數(shù)提供了一種簡(jiǎn)單的方式,可以在應(yīng)用程序中對(duì)數(shù)據(jù)進(jìn)行壓縮,適用于需要減小數(shù)據(jù)體積的場(chǎng)景,比如網(wǎng)絡(luò)傳輸或數(shù)據(jù)存儲(chǔ)。

// 單個(gè)文件限制大小為 100M 
#define MAX_SRC_FILE_SIZE (100*1024*1024)

/**
 * @brief 壓縮指定文件的數(shù)據(jù)
 *
 * @param pszCompressFileName 待壓縮文件的路徑
 * @param ppCompressData 保存壓縮后數(shù)據(jù)的指針
 * @param pdwCompressDataSize 傳入時(shí)為壓縮緩沖區(qū)的大小,傳出時(shí)為實(shí)際壓縮后數(shù)據(jù)的大小
 * @return 壓縮是否成功,成功返回 TRUE,否則返回 FALSE
 */
BOOL CompressData(char *pszCompressFileName, BYTE **ppCompressData, DWORD *pdwCompressDataSize)
{
  HANDLE hFile = CreateFile(pszCompressFileName, GENERIC_READ,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
    FILE_ATTRIBUTE_ARCHIVE, NULL);

  // 檢查文件句柄是否有效
  if (INVALID_HANDLE_VALUE == hFile)
  {
    return FALSE;
  }

  // 獲取文件大小
  DWORD dwFileSize = GetFileSize(hFile, NULL);

  // 檢查文件大小是否超過限制
  if (MAX_SRC_FILE_SIZE < dwFileSize)
  {
    CloseHandle(hFile);
    return FALSE;
  }

  DWORD dwDestDataSize = dwFileSize;

  // 分配源數(shù)據(jù)和目標(biāo)數(shù)據(jù)的內(nèi)存
  BYTE *pSrcData = new BYTE[dwFileSize];
  if (NULL == pSrcData)
  {
    CloseHandle(hFile);
    return FALSE;
  }

  BYTE *pDestData = new BYTE[dwDestDataSize];
  if (NULL == pDestData)
  {
    delete[] pSrcData;
    CloseHandle(hFile);
    return FALSE;
  }

  DWORD dwRet = 0;

  // 讀取源數(shù)據(jù)
  ReadFile(hFile, pSrcData, dwFileSize, &dwRet, NULL);

  // 檢查讀取是否成功
  if ((0 >= dwRet) || (dwRet != dwFileSize))
  {
    delete[] pDestData;
    delete[] pSrcData;
    CloseHandle(hFile);
    return FALSE;
  }

  int iRet = 0;

  // 壓縮數(shù)據(jù)
  do
  {
    iRet = compress(pDestData, &dwDestDataSize, pSrcData, dwFileSize);

    // 壓縮成功,退出循環(huán)
    if (0 == iRet)
    {
      break;
    }
    // 輸出緩沖區(qū)不足,增加緩沖區(qū)大小并重試
    else if (-5 == iRet)
    {
      delete[] pDestData;
      pDestData = NULL;
      dwDestDataSize = dwDestDataSize + (100 * 1024);
      pDestData = new BYTE[dwDestDataSize];

      // 分配新的目標(biāo)數(shù)據(jù)內(nèi)存
      if (NULL == pDestData)
      {
        delete[] pSrcData;
        CloseHandle(hFile);
        return FALSE;
      }
    }
    // 壓縮失敗,釋放內(nèi)存并返回失敗
    else
    {
      delete[] pDestData;
      pDestData = NULL;
      delete[] pSrcData;
      pSrcData = NULL;
      CloseHandle(hFile);
      return FALSE;
    }
  } while (TRUE);

  // 保存壓縮后數(shù)據(jù)的指針和實(shí)際大小
  *ppCompressData = pDestData;
  *pdwCompressDataSize = dwDestDataSize;

  // 釋放源數(shù)據(jù)內(nèi)存
  delete[] pSrcData;

  // 關(guān)閉文件句柄
  CloseHandle(hFile);

  // 返回壓縮成功
  return TRUE;
}

文件解壓縮

uncompress 函數(shù)是 zlib 庫(kù)提供的用于數(shù)據(jù)解壓縮的函數(shù),通過該函數(shù)可以將壓縮后的數(shù)據(jù)解壓縮還原。下面是一個(gè)示例,演示了如何使用 zlib 庫(kù)進(jìn)行文件解壓縮。

它的原型如下:

int uncompress(Bytef* dest, uLongf* destLen, const Bytef* source, uLong sourceLen);
  • dest:指向存放解壓縮后數(shù)據(jù)的緩沖區(qū)的指針。
  • destLen:傳入時(shí)為解壓縮緩沖區(qū)的大小,傳出時(shí)為實(shí)際解壓縮后數(shù)據(jù)的大小。
  • source:指向待解壓縮數(shù)據(jù)的緩沖區(qū)的指針。
  • sourceLen:待解壓縮數(shù)據(jù)的大小。

uncompress 函數(shù)的作用是將 source 指向的數(shù)據(jù)進(jìn)行解壓縮,并將結(jié)果存放在 dest 指向的緩沖區(qū)中。destLen 傳入時(shí)應(yīng)該是 dest 緩沖區(qū)的大小,函數(shù)執(zhí)行后,destLen 會(huì)更新為實(shí)際解壓縮后數(shù)據(jù)的大小。

函數(shù)返回值為解壓縮的執(zhí)行狀態(tài),可能的返回值包括:

  • Z_OK:解壓縮成功。
  • Z_MEM_ERROR:內(nèi)存分配失敗。
  • Z_BUF_ERROR:解壓縮輸出緩沖區(qū)不足。
  • Z_DATA_ERROR:輸入數(shù)據(jù)錯(cuò)誤或損壞。

uncompress 函數(shù)實(shí)際上是使用 DEFLATE 算法進(jìn)行解壓縮,與 compress 函數(shù)相對(duì)應(yīng)。這兩個(gè)函數(shù)共同構(gòu)成了 zlib 庫(kù)中的基本數(shù)據(jù)壓縮和解壓縮功能。

在實(shí)際應(yīng)用中,可以使用這兩個(gè)函數(shù)來處理需要壓縮和解壓縮的數(shù)據(jù),例如在網(wǎng)絡(luò)通信中減小數(shù)據(jù)傳輸量或在存儲(chǔ)數(shù)據(jù)時(shí)減小占用空間。

/**
 * @brief 解壓指定文件的數(shù)據(jù)
 *
 * @param pszUncompressFileName 待解壓文件的路徑
 * @param ppUncompressData 保存解壓后數(shù)據(jù)的指針
 * @param pdwUncompressDataSize 傳入時(shí)為解壓緩沖區(qū)的大小,傳出時(shí)為實(shí)際解壓后數(shù)據(jù)的大小
 * @return 解壓是否成功,成功返回 TRUE,否則返回 FALSE
 */
BOOL UncompressData(char *pszUncompressFileName, BYTE **ppUncompressData, DWORD *pdwUncompressDataSize)
{
  HANDLE hFile = CreateFile(pszUncompressFileName, GENERIC_READ,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
    FILE_ATTRIBUTE_ARCHIVE, NULL);

  // 檢查文件句柄是否有效
  if (INVALID_HANDLE_VALUE == hFile)
  {
    return FALSE;
  }

  // 獲取文件大小
  DWORD dwFileSize = GetFileSize(hFile, NULL);

  // 設(shè)置目標(biāo)數(shù)據(jù)緩沖區(qū)大小
  DWORD dwDestDataSize = MAX_SRC_FILE_SIZE;

  // 分配源數(shù)據(jù)和目標(biāo)數(shù)據(jù)的內(nèi)存
  BYTE *pSrcData = new BYTE[dwFileSize];
  if (NULL == pSrcData)
  {
    CloseHandle(hFile);
    return FALSE;
  }

  BYTE *pDestData = new BYTE[dwDestDataSize];
  if (NULL == pDestData)
  {
    delete[] pSrcData;
    CloseHandle(hFile);
    return FALSE;
  }

  DWORD dwRet = 0;

  // 讀取源數(shù)據(jù)
  ReadFile(hFile, pSrcData, dwFileSize, &dwRet, NULL);

  // 檢查讀取是否成功
  if ((0 >= dwRet) || (dwRet != dwFileSize))
  {
    delete[] pDestData;
    delete[] pSrcData;
    CloseHandle(hFile);
    return FALSE;
  }

  int iRet = 0;

  // 解壓縮數(shù)據(jù)
  do
  {
    iRet = uncompress(pDestData, &dwDestDataSize, pSrcData, dwFileSize);

    // 解壓縮成功,退出循環(huán)
    if (0 == iRet)
    {
      break;
    }
    // 輸出緩沖區(qū)不足,增加緩沖區(qū)大小并重試
    else if (-5 == iRet)
    {
      delete[] pDestData;
      pDestData = NULL;
      dwDestDataSize = dwDestDataSize + (100 * 1024);
      pDestData = new BYTE[dwDestDataSize];

      // 分配新的目標(biāo)數(shù)據(jù)內(nèi)存
      if (NULL == pDestData)
      {
        delete[] pSrcData;
        CloseHandle(hFile);
        return FALSE;
      }
    }
    // 解壓縮失敗,釋放內(nèi)存并返回失敗
    else
    {
      delete[] pDestData;
      pDestData = NULL;
      delete[] pSrcData;
      pSrcData = NULL;
      CloseHandle(hFile);
      return FALSE;
    }
  } while (TRUE);

  // 保存解壓后數(shù)據(jù)的指針和實(shí)際大小
  *ppUncompressData = pDestData;
  *pdwUncompressDataSize = dwDestDataSize;

  // 釋放源數(shù)據(jù)內(nèi)存
  delete[] pSrcData;

  // 關(guān)閉文件句柄
  CloseHandle(hFile);

  // 返回解壓成功
  return TRUE;
}

演示示例

下面是一個(gè)包含文件壓縮和解壓縮的完整示例,展示了如何將文件進(jìn)行壓縮保存,然后解壓還原。

調(diào)用CompressData壓縮文件,返回結(jié)果pCompressData存放文件內(nèi)存字節(jié),結(jié)果dwCompressDataSize存放長(zhǎng)度,并調(diào)用SaveToFile保存到本地。

int main(int argc, char* argv[])
{
  BOOL bRet = FALSE;
  BYTE *pCompressData = NULL;
  DWORD dwCompressDataSize = 0;

  // 壓縮文件
  bRet = CompressData("d:\\test.exe", &pCompressData, &dwCompressDataSize);
  if (TRUE == bRet)
  {
    std::cout << "已壓縮" << std::endl;
  }

  // 保存壓縮數(shù)據(jù)為文件
  bRet = SaveToFile("d:\\text.zlib", pCompressData, dwCompressDataSize);
  if (TRUE == bRet)
  {
    std::cout << "已保存到文件" << std::endl;
  }

  // 釋放內(nèi)存
  delete[]pCompressData;
  pCompressData = NULL;

  system("pause");
  return 0;
}

調(diào)用UncompressData解壓縮文件,返回結(jié)果pUncompressData存放文件內(nèi)存字節(jié),結(jié)果dwUncompressDataSize存放長(zhǎng)度,并調(diào)用SaveToFile保存到本地。

int main(int argc, char* argv[])
{
  BOOL bRet = FALSE;
  BYTE *pUncompressData = NULL;
  DWORD dwUncompressDataSize = 0;

  // 解壓文件
  bRet = UncompressData("d:\\test.zlib", &pUncompressData, &dwUncompressDataSize);
  if (TRUE == bRet)
  {
    std::cout << "已解壓" << std::endl;
  }

  // 保存解壓數(shù)據(jù)為文件
  bRet = SaveToFile("d:\\test.exe", pUncompressData, dwUncompressDataSize);
  if (TRUE == bRet)
  {
    std::cout << "已保存到文件" << std::endl;
  }

  // 釋放內(nèi)存
  delete[]pUncompressData;
  pUncompressData = NULL;

  system("pause");
  return 0;
}

編譯時(shí)可能會(huì)提示無法生成SAFESEH影響的報(bào)錯(cuò)信息,如下圖所示;

此時(shí)打開項(xiàng)目屬性頁(yè),找到鏈接器,高級(jí)選項(xiàng)卡,將映像安全處理改為否即可,如下圖所示;

結(jié)論

通過使用 zlib 庫(kù),我們可以方便地在應(yīng)用程序中實(shí)現(xiàn)數(shù)據(jù)的壓縮和解壓縮功能。這對(duì)于需要減小數(shù)據(jù)傳輸量或在存儲(chǔ)數(shù)據(jù)時(shí)減小占用空間的場(chǎng)景非常有用。在實(shí)際應(yīng)用中,可以根據(jù)需要調(diào)整緩沖區(qū)大小和處理流程,以適應(yīng)不同的數(shù)據(jù)處理需求。

以上就是C/C++使用Zlib實(shí)現(xiàn)文件的壓縮與解壓的詳細(xì)內(nèi)容,更多關(guān)于C++ Zlib文件壓縮與解壓的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++ primer超詳細(xì)講解泛型算法

    C++ primer超詳細(xì)講解泛型算法

    泛型編程,故如其名,是一個(gè)泛化的編程方式。其實(shí)現(xiàn)原理為程序員編寫一個(gè)函數(shù)/類的代碼示例,讓編譯器去填補(bǔ)出不同的函數(shù)實(shí)現(xiàn)
    2022-07-07
  • C語(yǔ)言深入淺出講解順序表的實(shí)現(xiàn)

    C語(yǔ)言深入淺出講解順序表的實(shí)現(xiàn)

    線性表是最簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),而順序表又是最簡(jiǎn)單的線性表,其基本思想是用一段地址連續(xù)的儲(chǔ)存單元依次存儲(chǔ)線性表的數(shù)據(jù)元素,比如我們常用的一維數(shù)組,下面代碼實(shí)現(xiàn)了順序表的定義以及基本操作
    2022-04-04
  • 理解數(shù)據(jù)結(jié)構(gòu)

    理解數(shù)據(jù)結(jié)構(gòu)

    本文是對(duì)數(shù)據(jù)結(jié)構(gòu)對(duì)編程的重要性,數(shù)據(jù)結(jié)構(gòu)對(duì)數(shù)據(jù)存儲(chǔ),數(shù)據(jù)處理,內(nèi)存工作,從宏觀上理解數(shù)據(jù)結(jié)構(gòu)
    2016-07-07
  • Qt數(shù)據(jù)庫(kù)應(yīng)用之?dāng)?shù)據(jù)打印到pdf

    Qt數(shù)據(jù)庫(kù)應(yīng)用之?dāng)?shù)據(jù)打印到pdf

    因?yàn)閤ls打開以后用戶可以修改數(shù)據(jù)造假之類的,而pdf默認(rèn)是不可編輯的,除非借助專業(yè)的工具,所以如果想要限定用戶導(dǎo)出數(shù)據(jù)不能被更改,那導(dǎo)出pdf是最佳選擇。所以本文將為代價(jià)介紹Qt實(shí)現(xiàn)數(shù)據(jù)打印到pdf的方法,需要的可以參考一下
    2022-01-01
  • QT6.5.3安裝教程(使用國(guó)內(nèi)源)

    QT6.5.3安裝教程(使用國(guó)內(nèi)源)

    本教程講述了使用國(guó)內(nèi)源安裝QT6.5.3版本的實(shí)現(xiàn)步驟,文中通過圖文示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • C語(yǔ)言順序查找算法介紹及示例

    C語(yǔ)言順序查找算法介紹及示例

    順序查找又稱線性查找,主要用于在線性表中進(jìn)行查找。順序查找通常分為對(duì)一般的無序線性表的順序查找和對(duì)按關(guān)鍵字有序的順序表的順序查找,下面我們來一探究竟
    2022-08-08
  • C++實(shí)現(xiàn)含附件的郵件發(fā)送功能

    C++實(shí)現(xiàn)含附件的郵件發(fā)送功能

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)含附件的郵件發(fā)送功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • C 語(yǔ)言常用方法技巧

    C 語(yǔ)言常用方法技巧

    本文主要介紹了C語(yǔ)言常用方法技巧。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-03-03
  • C++ 實(shí)現(xiàn)靜態(tài)單鏈表的實(shí)例

    C++ 實(shí)現(xiàn)靜態(tài)單鏈表的實(shí)例

    這篇文章主要介紹了C++ 實(shí)現(xiàn)靜態(tài)單鏈表的實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • C++ Qt開發(fā)之使用QProcess實(shí)現(xiàn)進(jìn)程管理

    C++ Qt開發(fā)之使用QProcess實(shí)現(xiàn)進(jìn)程管理

    Qt 是一個(gè)跨平臺(tái)C++圖形界面開發(fā)庫(kù),利用Qt可以快速開發(fā)跨平臺(tái)窗體應(yīng)用程序,本文將重點(diǎn)介紹如何運(yùn)用QProcess組件實(shí)現(xiàn)針對(duì)進(jìn)程的控制管理等,感興趣的可以了解下
    2024-03-03

最新評(píng)論

邵武市| 湟源县| 邻水| 扶绥县| 司法| 鹤峰县| 资源县| 延安市| 高雄市| 大庆市| 曲周县| 嫩江县| 香格里拉县| 平原县| 军事| 酒泉市| 东乌| 安仁县| 长垣县| 封丘县| 德清县| 建德市| 于都县| 江源县| 开远市| 灵山县| 阜新市| 甘洛县| 鄢陵县| 大港区| 黔西县| 乌苏市| 津南区| 阳曲县| 昌吉市| 昌黎县| 敦煌市| 诸城市| 连云港市| 通河县| 大渡口区|