zoukankan      html  css  js  c++  java
  • VC++ 解压有密码的.zip文件

    据说对.rar文件的解压是没有开源库的,而且好多软件都是收费的,因此这里便不再探讨对.rar文件的解压,下面研究一下.zip文件。
     
    不可否认,zlib是当今应用最广泛的压缩与解压缩.zip文件的免费库之一,zlib是一种事实上的业界标准(不信可以自己去百度),而且用法简单,对于有密码的zip文件也能轻松应对(当然我们首先得知道解压所需的密码)。
     
    下面我将讲解一下如何用zlib.lib和minizip.lib来对一个带密码的.zip压缩文件进行解压。废话少说,开始分析:
     
    1. 将zlib.lib和minizip.lib放到工程下(因为是静态库,所以将两个文件与其他工程文件放到同一个目录中即可)
     
    2. 将ioapi.h和unzip.h和zip.h和zlib.h放到工程下(我为了看着清洁,为这几个文件建立了文件夹--zlib)
     
    3. 在工程的.cpp文件的头部,添加如下代码:
     
    #include "zlibunzip.h"
    #include "zlibzlib.h"
    #include "zlibzip.h"
     
    #pragma comment( lib, "zlib.lib" )    // 将静态库引用进来
    #pragma comment( lib, "minizip.lib" )
     
    好,经过以上三条,用zlib所需的环境已准备好(以上文件均可在网上下载到),很简单吧。
    废话少说,上代码:
     
    注:因为zip文件对于zlib来说相当于是以文件(个人觉得也可以理解为数据块)的形式存在的,在进行解压时,会把zip中的文件(文件夹)当成一块一块的数据进行读取,因此zlib会从zip文件中按顺序一个一个文件(文件夹)的读取,如果是文件,则写成文件,如果是文件夹,则需要用户来自己创立该文件夹的路径,因为zlib不能往不存在的路径中写文件(这是我经过测试发现的)。以上的注释是下面程序的执行过程
     
    #define ZIP_OPEN_FAILED    1
    #define ZIP_GETGLOBAL_FAILED  2
    #define ZIP_GETFILE_FAILED   3
    #define ZIP_CREATEFILE_FAILED  4
    #define ZIP_OPENPSDFILE_FAILED  5
    #define ZIP_OPENFILE_FAILED   6
    #define ZIP_READFILE_ERR   7
    #define MAX_BUFSIZE     4096 // 从zip文件中一次读取的最大缓冲值
    
    //函数名称:UnzipFile
    //函数功能:解压zip文件
    //输入参数:strFilePath 带解压zip文件的路径+名称
    //     strTmpPath  解压到这个路径下
    //     strPsd    密码
    //返 回 值:参考ConfigInfo.h
    int CUnzip::UnzipFile(CString strFilePath, CString strTmpPath, CString strPsd)
    {
     unzFile uf = NULL;
     unz_global_info *p_gInfo = NULL;
     unz_file_info   *p_fInfo = NULL;
     p_gInfo = new unz_global_info;
     p_fInfo = new unz_file_info;
     CString strZipPath = strFilePath;
     
     
     uf = unzOpen(strZipPath);     // 打开zip文件,返回文件句柄
     if (NULL == uf)
      return ZIP_OPEN_FAILED;     // 打开失败
     if (UNZ_OK != unzGetGlobalInfo(uf, p_gInfo))// 向*pglobal_info结构体中写入zip的信息
      return ZIP_GETGLOBAL_FAILED;   // 获取zip信息失败
     CString strZipFName(_T(""));     // 用于存放szZipFName
     CString strFolderName(_T(""));
     CString strDiskPath(_T(""));     // 创建磁盘路径(文件夹)时会用到
     CString strDiskFile(_T(""));     // 创建磁盘文件时会用到
     char szZipFName[MAX_PATH] = "0";   // 存放从zip中解析出来的“文件(信息块)”名字
     char szReadBuf[MAX_BUFSIZE] = "0";
     int  nNum = 0;       // unzReadCurrentFile读取的字符数
     DWORD dWrite = 0;       // 实际写入的字节数
     int nState = strFilePath.ReverseFind(_T('\'));
     //strTmpPath += CString(_T("")) + strFilePath.Mid(nState+1, strFilePath.ReverseFind(_T('.'))-nState-1);
     CreateFilePath(strTmpPath);     // strFilePath为F:\file.zip,解压到E:\TEST下,则先创建目录E:\TEST\file
     for (int i = 0; i < p_gInfo->number_entry; i++)
     {
      // for reading the content of the current zipfile, you can open it, read data
         // from it, and close it (you can close it before reading all the file)
      if (UNZ_OK != unzGetCurrentFileInfo(uf, p_fInfo, szZipFName, MAX_PATH, NULL, 0, NULL, 0))
       return ZIP_GETFILE_FAILED;
      switch (p_fInfo->external_fa)
      {
      case FILE_ATTRIBUTE_DIRECTORY:  // 文件夹
       {
        FormatDirectorys(szZipFName);
        strFolderName = szZipFName;
        strDiskPath = strTmpPath + CString(_T("")) + strFolderName;
        
        CreateFilePath(strDiskPath); // 创建目录(文件夹)
        break;
       }
       
      default:       // 文件
       {
        FormatDirectorys(szZipFName);
        strZipFName = szZipFName;
        strDiskFile = strTmpPath + CString(_T("")) + strZipFName;
        HANDLE hFile = CreateFile(strDiskFile, GENERIC_WRITE, // 对文件进行只写访问
              0,        // 独占对文件的访问
              NULL, OPEN_ALWAYS,    // 打开已有文件,若存在则直接打开,否则创建新文件
              FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_WRITE_THROUGH, // 隐藏文件 | 进制对文件写入操作进行缓存以减少数据丢失的可能性
              NULL);
        if (INVALID_HANDLE_VALUE == hFile)
         return ZIP_CREATEFILE_FAILED;      // 文件打开(创建)失败
        if (strPsd.IsEmpty())
        {
         if (UNZ_OK != unzOpenCurrentFile(uf))
         {
          CloseHandle(hFile);   // 打开失败
          return ZIP_OPENFILE_FAILED;
         }
        }
        else
        {
         if (UNZ_OK != unzOpenCurrentFilePassword(uf, strPsd))
         {
          CloseHandle(hFile);   // 打开有密码的zip压缩包中的文件失败
          return ZIP_OPENPSDFILE_FAILED;
         }
        }
        while(TRUE)
        {
         nNum = 0;
         memset(szReadBuf, 0, MAX_BUFSIZE);
         nNum = unzReadCurrentFile(uf, szReadBuf, MAX_BUFSIZE); // 从zip中读数据
         if (nNum < 0)
         {
          unzCloseCurrentFile(uf);
          CloseHandle(hFile);
          return ZIP_READFILE_ERR;
         }
         else if (nNum == 0)
         {
          unzCloseCurrentFile(uf);
          CloseHandle(hFile);
          break;
         }
         else
         {
          if (!WriteFile(hFile, szReadBuf, MAX_BUFSIZE, &dWrite, NULL))// 往本地磁盘写数据
          {
           unzCloseCurrentFile(uf);
           CloseHandle(hFile);
           return (GetLastError());
          }
         }
        }
        break;
       }
       
      }
      unzGoToNextFile(uf);
     }
     if (uf)
      unzClose(uf);
     return -1;
    }
     
    // 在磁盘中创建路径strPath
    void C**Dlg::OnCreateFilePath(CString strPath)
    {
     int nPos;
     CString strFolder("");
     for (nPos = 0; nPos != -1; nPos = strPath.Find(""))
     {
      nPos = strPath.Find("");
      strFolder += strPath.Left(nPos);
      if (!PathFileExists(strFolder))
      {
       CreateDirectory(strFolder, NULL);
      }
      strPath = strPath.Mid(nPos+1);
      strFolder += "";
     }
    }
     


  • 相关阅读:
    Fiddler 教程
    ios iOS手势识别的详细使用(拖动,缩放,旋转,点击,手势依赖,自定义手势)
    ios 生成一个动态的随机的头像/随机数的操作
    在工程中如何使用一个公用的页面
    使用手势,让键盘在点击空白处消失
    ios开发之--iOS 11适配:iOS11导航栏返回偏移
    svn 操作字母的提示
    字面量
    控制 打开和关闭远程推送通知
    常见结构体 日期 字符串的操作 很实用
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318269.html
Copyright © 2011-2022 走看看