VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1581|回复: 2

[原创] Zlib库如何压缩/解压缩文件夹

[复制链接]
70_avatar_middle
在线会员 发表于 2015-11-24 16:40:27 | 显示全部楼层 |阅读模式
本帖最后由 QSir 于 2015-11-24 16:40 编辑

        网上大部分对zlib的使用介绍都是压缩内容的,很少涉及到对文件夹的操作,但是很多时候我们需要对文件进行打包,所以~~~~
        废话不多说,直接上代码~~~~~~

  1. //addFileToZip:把文件压缩到zip中
  2. //把zipName文件压缩到szPath中
  3. //注意:此生成不了空目录
  4. //////////////////////////////////////////////////////////////////////////
  5. void CZipManager::addFileToZip(zipFile zf, const char* zipName, const char* szPath)
  6. {
  7.         char fileName[MAX_PATH] = {};       
  8.         if (szPath[1] == ':')                //表示是盘符,也即绝对路径
  9.         {
  10.                 strcpy_s(fileName, MAX_PATH, &szPath[3]);
  11.         }
  12.         else                      //可能是多级相对目录
  13.         {
  14.                 int count = 0;
  15.                 while (szPath[count] == '.' || szPath[count] == '\\')
  16.                 {
  17.                         ++count;
  18.                 }
  19.                 strcpy_s(fileName, MAX_PATH, &szPath[count]);
  20.         }

  21.         strcat_s(fileName, MAX_PATH, zipName);

  22.         zip_fileinfo zi = {};
  23.         zipOpenNewFileInZip(zf, fileName, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);

  24.         memset(fileName, 0, MAX_PATH);
  25.         strcpy_s(fileName, MAX_PATH, szPath);
  26.         strcat_s(fileName, MAX_PATH, zipName);        //由于szPath是从recursiveFloder中传过来的,故末尾一定有'\\'

  27.         FILE* srcfp = NULL;
  28.         if (0 != fopen_s(&srcfp, fileName, "rb"))        //一定要b,否则读不到非文本文件
  29.         {
  30.                 //printf("open file error\n");
  31.                 //getchar();
  32.                 zipCloseFileInZip(zf);
  33.                 return;
  34.         }

  35.         char buf[100 * 1024] = {};
  36.         int numBytes = 0;
  37.         while (!feof(srcfp))
  38.         {
  39.                 numBytes = fread(buf, 1, sizeof(buf), srcfp);
  40.                 zipWriteInFileInZip(zf, buf, numBytes);
  41.                 if (ferror(srcfp))
  42.                         break;

  43.                 memset(buf, 0, sizeof(buf));        //每次使用都要清零
  44.         }
  45.         fclose(srcfp);

  46.         zipCloseFileInZip(zf);
  47. }
复制代码

  1. //递归文件夹,把遍历的文件进行压缩
  2. BOOL CZipManager::recursiveFloder(zipFile zf, const char* strPath)
  3. {
  4.         if (strPath == NULL)
  5.                 return FALSE;

  6.         char szPath[MAX_PATH] = {};
  7.         char szDestPath[MAX_PATH] = {};
  8.         char szStrTmpPath[MAX_PATH] = {};        //让其带上\\以表示目录
  9.         int len = strlen(strPath);
  10.         if (strPath[len - 1] == '\\')
  11.         {
  12.                 strcpy_s(szStrTmpPath, MAX_PATH, strPath);
  13.         }
  14.         else
  15.         {
  16.                 strcpy_s(szStrTmpPath, MAX_PATH, strPath);
  17.                 strcat_s(szStrTmpPath, MAX_PATH, "\");
  18.         }

  19.         strcpy_s(szPath, MAX_PATH, szStrTmpPath);
  20.         strcat_s(szPath, MAX_PATH, "*.*");

  21.         WIN32_FIND_DATAA findFileData;
  22.         HANDLE hFind = ::FindFirstFileA(szPath, &findFileData);
  23.         if (INVALID_HANDLE_VALUE == hFind)
  24.         {
  25.                 return FALSE;
  26.         }

  27.         while (TRUE)
  28.         {
  29.                 if (findFileData.cFileName[0] != '.')
  30.                 {
  31.                         memset(szPath, 0, MAX_PATH);
  32.                         strcpy_s(szPath, MAX_PATH, szStrTmpPath);

  33.                         if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)        //文件夹/目录
  34.                         {
  35.                                 strcat_s(szPath, MAX_PATH, findFileData.cFileName);
  36.                                 recursiveFloder(zf, szPath); //递归子目录文件  
  37.                         }
  38.                         else
  39.                         {
  40.                                 addFileToZip(zf, findFileData.cFileName, szPath);
  41.                         }
  42.                 }

  43.                 int bRet = ::FindNextFileA(hFind, &findFileData);
  44.                 if (!bRet)
  45.                 {
  46.                         break;
  47.                 }
  48.         }
  49.         ::FindClose(hFind);
  50.         return TRUE;
  51. }
复制代码

  1. //计算一个文件夹下的所有文件个数(包括子文件夹)
  2. unsigned int CZipManager::countFiles(const char* strPath)
  3. {
  4.         if (strPath == NULL)
  5.                 return 0;

  6.         char szPath[MAX_PATH] = {};
  7.         char szDestPath[MAX_PATH] = {};

  8.         strcpy_s(szPath, MAX_PATH, strPath);

  9.         int len = strlen(szPath);
  10.         if (szPath[len - 1] == '\\')
  11.         {
  12.                 strcat_s(szPath, MAX_PATH, "*.*");
  13.         }
  14.         else
  15.         {
  16.                 strcat_s(szPath, MAX_PATH, "\\*.*");
  17.         }

  18.         WIN32_FIND_DATAA findFileData;
  19.         HANDLE hFind = ::FindFirstFileA(szPath, &findFileData);
  20.         if (INVALID_HANDLE_VALUE == hFind)
  21.         {
  22.                 return 0;
  23.         }

  24.         while (TRUE)
  25.         {
  26.                 if (findFileData.cFileName[0] != '.')
  27.                 {
  28.                         memset(szPath, 0, MAX_PATH);
  29.                         strcpy_s(szPath, MAX_PATH, strPath);

  30.                         if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)        //文件夹/目录
  31.                         {
  32.                                 int len = strlen(szPath);
  33.                                 if (szPath[len - 1] == '\\')
  34.                                 {

  35.                                 }
  36.                                 else
  37.                                 {
  38.                                         strcat_s(szPath, MAX_PATH, "\");
  39.                                 }
  40.                                
  41.                                 strcat_s(szPath, MAX_PATH, findFileData.cFileName);

  42.                                 countFiles(szPath); //递归子目录文件  
  43.                         }
  44.                         else
  45.                         {
  46.                        
  47.                                 ++m_maxCount;
  48.                         }
  49.                 }

  50.                 int bRet = ::FindNextFileA(hFind, &findFileData);
  51.                 if (!bRet)
  52.                 {
  53.                         break;
  54.                 }
  55.         }
  56.         ::FindClose(hFind);

  57.         return m_maxCount;
  58. }
复制代码

  1. //压缩文件夹
  2. void CZipManager::zipFloder(const char* dirName, const char* zipFileName)
  3. {
  4.         zipFile newZipFile = zipOpen(zipFileName, APPEND_STATUS_CREATE); //创建zip文件  
  5.         if (newZipFile == NULL)
  6.         {
  7.                 printf("无法创建!\n");
  8.                 getchar();
  9.                 return;
  10.         }

  11.         BOOL flag = recursiveFloder(newZipFile, dirName);
  12.         zipClose(newZipFile, NULL); //关闭zip文件
  13.         return;
  14. }
复制代码

  1. //解压缩文件
  2. BOOL CZipManager::unzCurrentFile(unzFile uf, const char* szDestFloder)
  3. {
  4.         char szFilePath[MAX_PATH] = {};
  5.         char szDestFile[MAX_PATH] = {};

  6.         if (szDestFloder == NULL)
  7.                 return FALSE;

  8.         strcpy_s(szDestFile, MAX_PATH, szDestFloder);

  9.         unz_file_info unzfi;
  10.         if (unzGetCurrentFileInfo(uf, &unzfi, szFilePath, sizeof(szFilePath), NULL, 0, NULL, 0) != UNZ_OK)
  11.         {
  12.                 return FALSE;
  13.         }

  14.         if (unzOpenCurrentFile(uf) != UNZ_OK)
  15.         {
  16.                 return FALSE;
  17.         }

  18.         int nLen = strlen(szDestFloder);
  19.         if (szDestFloder[nLen-1] != '\\')        //如果目的文件夹没有带\\,则需加上
  20.         {
  21.                 strcat_s(szDestFile, MAX_PATH, "\");
  22.         }
  23.         strcat_s(szDestFile, MAX_PATH, szFilePath);

  24.         nLen = strlen(szDestFile);
  25.         char* ptemp = szDestFile;
  26.         while (ptemp[nLen--] != '\\' && nLen != 0);        //找到最后一级文件夹

  27.         if (nLen != 0)
  28.         {
  29.                 char floder[MAX_PATH] = {};
  30.                 strncpy_s(floder, szDestFile, nLen+1);

  31.                 if (_access(floder, 0) == -1)
  32.                 {
  33.                         int err = SHCreateDirectoryExA(NULL, floder, NULL);        //必须为绝对路径
  34.                         if (!(err == ERROR_SUCCESS || err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS))
  35.                         {
  36.                                 return FALSE;
  37.                         }
  38.                 }
  39.         }

  40.         HANDLE hFile = CreateFileA(szDestFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
  41.         if (hFile == INVALID_HANDLE_VALUE)
  42.         {
  43.                 return FALSE;
  44.         }

  45.         const DWORD BUFFER_SIZE = 1024 * 100;
  46.         BYTE buf[BUFFER_SIZE] = {};

  47.         while (true)
  48.         {
  49.                 int nSize = unzReadCurrentFile(uf, buf, BUFFER_SIZE);

  50.                 if (nSize < 0)
  51.                 {
  52.                         CloseHandle(hFile);
  53.                         return FALSE;
  54.                 }
  55.                 else if (nSize == 0)
  56.                 {
  57.                         break;
  58.                 }
  59.                 else
  60.                 {
  61.                         DWORD dwWritten = 0;

  62.                         if (!WriteFile(hFile, buf, (DWORD)nSize, &dwWritten, NULL) || dwWritten != (DWORD)nSize)
  63.                         {
  64.                                 CloseHandle(hFile);
  65.                                 return FALSE;
  66.                         }
  67.                 }

  68.                 memset(buf, 0, sizeof(buf));
  69.         }
  70.         CloseHandle(hFile);
  71.         return TRUE;
  72. }
复制代码

  1. unsigned int CZipManager::countZipFiles(const char* zipPath)        //计算一个压缩文件夹内的文件数
  2. {
  3.         unzFile uf = unzOpen(zipPath);

  4.         if (uf == NULL)
  5.         {
  6.                 return 0;
  7.         }

  8.         unz_global_info unzgi = {};
  9.         if (unzGetGlobalInfo(uf, &unzgi) != UNZ_OK)
  10.         {
  11.                 return 0;
  12.         }

  13.         unsigned int count = unzgi.number_entry;
  14.         unzClose(uf);

  15.         return count;
  16. }

  17. //解压缩文件夹
  18. BOOL CZipManager::unzFloder(const char* szSourceFile, const char* szDestFloder)
  19. {
  20.         unzFile uf = unzOpen(szSourceFile);        //不能打开空的zip文件
  21.         unz_global_info unzgi = {};

  22.         if (uf == NULL)
  23.         {
  24.                 //return FALSE;
  25.                 goto ErrorHanding;
  26.         }

  27.         if (unzGetGlobalInfo(uf, &unzgi) != UNZ_OK)
  28.         {
  29.                 //return FALSE;
  30.                 goto ErrorHanding;
  31.         }
  32.        
  33.         if (_access(szDestFloder, 0) == -1)
  34.         {
  35.                 int err = SHCreateDirectoryExA(NULL, szDestFloder, NULL);        //必须为绝对路径
  36.                 if (!(err == ERROR_SUCCESS || err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS))
  37.                 {
  38.                         //return FALSE;
  39.                         goto ErrorHanding;
  40.                 }
  41.         }

  42.         //int err = _mkdir(szDestFloder);        //_mkdir不能创建多级目录
  43.         //if (err == ENOENT)
  44.         //{
  45.         //        //return FALSE;
  46.         //        goto ErrorHanding;
  47.         //}
  48.         for (unsigned int i = 0; i < unzgi.number_entry; ++i)
  49.         {
  50.                 unzCurrentFile(uf, szDestFloder);
  51.                 if (unzGoToNextFile(uf) != UNZ_OK)
  52.                 {
  53.                         break;
  54.                 }
  55.         }

  56.         unzClose(uf);
  57.         return TRUE;

  58. ErrorHanding:
  59.         if (uf != NULL)
  60.                 unzClose(uf);
  61.         return FALSE;
  62. }
复制代码


        大部分代码都在这了,当然还是有很多的不完善的地方,比如传绝对路径的问题,这个可以使用_mkdir自己一层一层创建的话,可以不使用绝对路径,然后解压时不能按指定的目录进行解压,这个在解压的时候先进行目录的匹配判断,这些都不难,多几行代码而已~~~~~
        或许还有没发现的错误,欢迎指正,整个工程文件都在附件中,vs2013如何编译Zlib库,前一篇帖子的附件中有超详细说明~~~~
       

ZlibManager.rar

783.64 KB, 下载次数: 16, 下载积分: 驿站币 -1

源码+zlib库源码都在里面

评分

参与人数 2威望 +2 驿站币 +5 热心值 +5 收起 理由
24_avatar_small bacsj118 + 2 + 2 很给力!
51_avatar_small Syc + 2 + 3 + 3 感谢楼主分享这么好的东西,支持!

查看全部评分





上一篇:VC&amp;nbsp;获取静态文本控件和文本框控件上的文本方法
下一篇:TYVJ 登录器 发布!
51_avatar_middle
online_admins 发表于 2015-11-24 16:45:40 | 显示全部楼层
多谢楼主分享,大家有福啦Zlib库如何压缩/解压缩文件夹
16_avatar_middle
在线会员 发表于 2015-11-24 18:16:19 | 显示全部楼层
多谢楼主分享
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-6-19 20:08

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表