VC++使用开源的zip.cpp和unzip.cpp实现压缩包的创建与解压(附源码)

目录

1、使用场景

2、压缩包的创建

3、压缩包的解压

4、CloseZipZ和CloseZipU两接口的区别 

5、开源zip.cpp和unzip.cpp文件的下载


      有时我们需要在代码中实现压缩包的创建以及对压缩包的解压,开源的win32版本的zip.cpp和unzip.cpp给我们提供了途径和办法,本文我们就来讲讲如何使用这两个开源的cpp文件实现压缩包的创建和解压。

1、使用场景

       压缩包的解压一般用在自制的安装包(自己实现的安装包程序,不使用InstallShield等打包工具)中。我们一般将要拷贝到安装路径下的文件打成zip包放置到安装包工程的资源中,集成到exe文件中,在执行安装包安装时,将zip压缩包从资源中取出来,解压到磁盘上,然后再将文件拷贝到安装路径中。

2、压缩包的创建

       为了避免和其他头文件出现函数重名的冲突,我们在两个CPP对应的头文件中添加了命名空间INS_ZIP。我们首先调用CreateZip接口创建一个压缩包,然后调用ZipAdd将文件添加到压缩包中。

VC++使用开源的zip.cpp和unzip.cpp实现压缩包的创建与解压(附源码)_第1张图片

       如果要将文件夹添加到压缩包中,则需要遍历文件夹中的文件,然后在调用ZipAdd时要把文件夹中的文件相对于压缩包的相对路径传递给ZipAdd。对文件夹的操作,我们已经封装成名叫AddZipFolder的接口。

       创建压缩包的代码如下所示,我们将config.ini文件和msssdk文件夹添加到压缩包中:

// 先创建zip包.zip文件,在把各个文件和文件夹添加进去,对于文件夹需要
// 递归遍历
INS_ZIP::HZIP hz = INS_ZIP::CreateZip( strUserZipFile, 0 );
if ( hz == NULL )
{
     return;
}

// 压缩包最上层的文件直接调用ZipAdd添加到压缩包中即可
CString strConfigFilePath = _T("D:\\config.ini");
if ( PathFileExists( strConfigFilePath ) )
{
    INS_ZIP::ZipAdd( hz, _T("login.ini"), strConfigFilePath );
}

// 如果是待压缩的中间包含文件夹,则在调用函数时,要自己维护文件的
// 层次关系,即加入的文件在当前zip包中应该是相对路径,所以调用
// AddZipFolder在传递绝对路径的同时,还要传递Users的相对路径
CString strZipDir = _T("D:\\msssdk");
if ( PathFileExists( strZipDir ) )
{
    AddZipFolder( hz, strZipDir, _T("msssdk") );
}

INS_ZIP::CloseZipZ( hz );

        处理文件夹的接口AddZipFolder实现如下:

void AddZipFolder( INS_ZIP::HZIP hz, LPCTSTR lpszDir, LPCTSTR lpRelPath )
{
	CString strFindFileName = lpszDir;
	strFindFileName += _T("\\*.*");  
	WIN32_FIND_DATA wfd;
	HANDLE hFindFile = FindFirstFile( strFindFileName, &wfd );
	if ( hFindFile == INVALID_HANDLE_VALUE )
	{
		return;
	}

	CString strFilePath;
	CString strRelPath;
	while ( 1 )      
	{                     
		if ( wfd.cFileName[0] != '.' )          
		{          
			strFilePath = lpszDir;
			strFilePath += _T("\\");
			strFilePath += wfd.cFileName;

			strRelPath = lpRelPath;
			strRelPath += _T("\\");
			strRelPath += wfd.cFileName;

			if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) // 目录
			{
				// 文件夹要递归调用
				AddZipFolder( hz, strFilePath, strRelPath );

				// 对于ZipAddFolder的调用,一般传入文加件名。如果文件夹中包含子文件夹,则要传入相对路径
				// 注意,不能不能传入绝对路径,因为ZipAddFolder会依次创建绝对路径中的文件。因为文件夹中
				// 包含子文件夹,比如msssdk\include,会先遍历到最上面的文件夹Users,
				// 在压缩包中线创建msssdk目录,当遍历到include,传入msssdk\include,由于父目录Users已经
				// 存在,所以只创建include目录

				// 相对路径,即加入的文件相对zip包的相对路径
				ZipAddFolder( hz, strRelPath );
			}
			else // 文件           
			{        
				// ZipAdd添加文件,要保证在压缩包中的相对位置,所以要传入相对路径strRelPath,最后一个参
				// 数则要传入待打包文件的完整路径
				ZipAdd( hz, (LPCTSTR)strRelPath, (LPCTSTR)strFilePath );
			}         
		} 

		if ( !FindNextFile( hFindFile, &wfd ) )
		{
			break;
		}
	}      

	FindClose( hFindFile );
}

3、压缩包的解压

      先调用OpenZip打开压缩包,然后调用GetZipItem获取压缩包中文件的个数,然后再for循环依次调用GetZipItem获取文件信息,依次调用UnzipItem将每个文件都解压出来,相关代码如下所示:

// 返回TRUE表示没有错误,返回FALSE表示有错误发生,
// strDstPath:解压出来的文件的存放路径,strZipName待解压的压缩包文件名(含绝对路径)
BOOL Unzip( CString strDstPath, CString strZipName )
{  
    BOOL bExistError = FALSE;
    SetCurrentDirectory( strDstPath );
    INS_UNZIP::HZIP hz = INS_UNZIP::OpenZip( strZipName, 0 );
    if ( hz == NULL )
    {
         return FALSE;
    }

    INS_UNZIP::ZIPENTRY ze;     
    INS_UNZIP::GetZipItem( hz, -1, &ze ); 
    int numitems = ze.index;
    for ( int i = 0; i < numitems; i++ )
    { 
        INS_UNZIP::GetZipItem( hz, i, &ze );
        DWORD dwRet = INS_UNZIP::UnzipItem( hz, i, ze.name );

        // 解压有错误
        if ( dwRet != 0 )
        {
            CString strLog;
            strLog.Format( _T("[Unzip]文件解压错误:%s,  lasterror: 0x%08X"), ze.name, dwRet );
            WriteLog( strLog );
            bExistError = TRUE;
        }
    }

    INS_UNZIP::CloseZipU( hz );  
    
    return !bExistError;
}

4、CloseZipZ和CloseZipU两接口的区别 

       在创建压缩包和解压压缩包之后,要记得调用关闭压缩包句柄的接口(CloseZipZ和CloseZipU两个接口),不然会有资源泄露。       

       这个地方要稍微区分一下CloseZipZCloseZipU两个接口,这两个接口咋一看上去很容易分不清。其实很简单,CloseZipZ接口的结尾Z对应zip首字母, CloseZipU接口的结尾U对应unzip首字母。 

       如果是调用CreateZip接口创建压缩包,将调用zip.cpp文件中的接口,关闭句柄时要使用对应的ClozeZipZ接口。

       如果是调用OpenZip接口打开压缩包进行解压,将调用unzip.cpp文件中的接口,关闭句柄时要使用对应的ClozeZipU接口。

5、开源zip.cpp和unzip.cpp文件的下载

       开源的zip.cpp和unzip.cpp及对应的头文件,可以到网盘中下载:

链接:https://pan.baidu.com/s/1yvFYkEs3Upxfqi2dmKVlQg 
提取码:p55w

你可能感兴趣的:(VC++常用功能代码封装,zip,unzip,创建压缩包,解压压缩包)