linux下使用libz解压整个目录

34 篇文章 0 订阅

libz用的比较多,在libz中有个minizip,实现了对压缩和解压缩的封装,

这里使用该文件封装为C++类,实现对整个压缩包的解压;

使用代码如下:main.cpp

//gcc zipHelper.cpp main.cpp ./minizip/ioapi.c  ./minizip/zip.c   ./minizip/unzip.c  -o testzip -lz -lstdc++


#include <iostream>
#include "zipHelper.h"

using namespace std;
 
int main(int argc, char** argv) {
	cPackFile packTool;
	cUnpackFile unpackTool;

	//packTool.CreateZipFromDir("/robin1/testZip/test", "/robin1/testZip/example.zip");


	unpackTool.CreateDirFromZip("/robin1/testZip/test1", "/robin1/testZip/example.zip");

	
	return 0;
}

调用的类文件:zipHelper.h

#pragma once
#ifndef ZIP_H
#define ZIP_H
#include <iostream>
#include <fstream>
#include <string>
#include "minizip/zip.h"
#include "minizip/unzip.h"

using namespace std;
 
class cPackFile
{
public:
	//将某个目录或者文件(dirName)压缩为zipFileName(.zip)文件
	int CreateZipFromDir(const string &dirName, const string & zipFileName);
	cPackFile();
	~cPackFile();
private:
	int count = 0;
	//递归添加子目录到zip文件  
	void CollectFilesInDirToZip(zipFile zf, const string & strPath, const string & parentDir);
 
	void AddFileToZip(zipFile zf, const string & fileNameInZip, const string & srcFile);
};
 
static inline bool IsFileExist(const string &pPath);
 
class cUnpackFile
{
private:
	bool splitDirAndName(const string &str, string& dir);
public:
	cUnpackFile();
	~cUnpackFile();
	void CreateDirFromZip(const string & dirName, const string &zipFileName);//解压到文件夹dirName
	void CreateFileFromZip(const string & fName, const string & zipFileName);//解压第一个文件到文件fName
};
 
#endif


源文件为:zipHelper.cpp

#include "zipHelper.h"
#include <stdio.h>

#include <fstream>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "PathUtil.h"

using namespace std;
using namespace oneapm;

//将文件添加到zip文件中,注意如果源文件srcFile为空则添加空目录
// fileNameInZip: 在zip文件中的文件名,包含相对路径
void cPackFile::AddFileToZip(zipFile zf, const string &fileNameInZip, const string &srcFile)
{
	FILE *srcfp = NULL;

	//初始化写入zip的文件信息
	// zip_fileinfo zi;
	zip_fileinfo zi = {0};

	zi.tmz_date.tm_sec = 0;
	zi.tmz_date.tm_min = 0;
	zi.tmz_date.tm_hour = 0;
	zi.tmz_date.tm_mday = 0;
	zi.tmz_date.tm_mon = 0;
	zi.tmz_date.tm_year = 0;
	zi.dosDate = 0;
	zi.internal_fa = 0;
	zi.external_fa = 0;

	//如果srcFile为空,加入空目录
	string new_file_name = fileNameInZip;
	if (srcFile == "")
	{
		new_file_name += "/";
	}

	//在zip文件中创建新文件
	zipOpenNewFileInZip(zf, new_file_name.c_str(), &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);

	if (srcFile != "")   // is a real file, or will be a dir name
	{
		//打开源文件
		srcfp = fopen(srcFile.c_str(), "rb");
		if (srcfp == NULL)
		{
			printf("无法添加文件: %s !\n", srcFile);
			zipCloseFileInZip(zf); //关闭zip文件
			return;
		}

		//读入源文件并写入zip文件
		char buf[100 * 1024]; // buffer
		int numBytes = 0;
		while (!feof(srcfp))
		{
			numBytes = fread(buf, 1, sizeof(buf), srcfp);
			zipWriteInFileInZip(zf, buf, numBytes);
			if (ferror(srcfp))
				break;
		}

		//关闭源文件
		fclose(srcfp);
	}

	count++;

	//关闭zip文件
	zipCloseFileInZip(zf);
}

//递归添加子目录到zip文件
// zip, real path in fs, basedir name in zip
void cPackFile::CollectFilesInDirToZip(zipFile zf, const string & strPath, const string & parentDir)
{
	if (false == PathUtil::isDirectory(strPath))
	{
		return;
	}


	DIR * p_dir = opendir(strPath.c_str());
	if (p_dir == NULL)
	{
		std::cout << "Opendir error: " << strerror(errno) << std::endl;
		return ;
	}

	string currentPath;
	string zipPath;

	int result = 0;
	struct dirent *p_dirent;
	while ((p_dirent = readdir(p_dir)) != NULL)
	{
		currentPath = strPath + "/" + p_dirent->d_name;   // fs name path
		zipPath = parentDir + "/" + p_dirent->d_name;     // path in zip

		if (PathUtil::isDirectory(currentPath) && (0 != strcmp(p_dirent->d_name, ".")) && (0 != strcmp(p_dirent->d_name, "..")))
		{
			AddFileToZip(zf, zipPath, "");					  //在zip文件中生成目录结构
			CollectFilesInDirToZip(zf, currentPath, zipPath); //递归收集子目录文件
			
		}
		else if ((0 != strcmp(p_dirent->d_name, ".")) && (0 != strcmp(p_dirent->d_name, "..")))
		{
			AddFileToZip(zf, zipPath, currentPath); //将文件添加到zip文件中
		}

	}

	closedir(p_dir);
}

//将某个目录或者文件(dirName)压缩为zipFileName(.zip)文件
int cPackFile::CreateZipFromDir(const string &dirName, const string &zipFileName)
{
	struct stat buffer;
	int ret = stat(dirName.c_str(), &buffer);
	if (ret != 0)
		return -1;

	zipFile newZipFile = zipOpen(zipFileName.c_str(), APPEND_STATUS_CREATE); //创建zip文件
	if (newZipFile == NULL)
	{
		printf("无法创建zip文件!\n");
		return -2;
	}

	// from  /robin1/test/dir    to ====>  dir
	string tempName = "";
	auto pos = dirName.find_last_of("\/");
	if (dirName.npos == pos)
	{
		tempName = dirName;
	}
	else
	{
		tempName = dirName.substr(pos + 1);
	}

	// only one file
	if (S_ISREG(buffer.st_mode))
	{
		AddFileToZip(newZipFile, tempName, dirName);
	}

	if (S_ISDIR(buffer.st_mode)) // is a directory
	{
		AddFileToZip(newZipFile, tempName, "");
		CollectFilesInDirToZip(newZipFile, dirName, tempName);
	}

	zipClose(newZipFile, NULL); //关闭zip文件

	return count;
}

cPackFile::cPackFile()
{
}

cPackFile::~cPackFile()
{
}

/
// test normal file
static inline bool IsFileExist(const string &pPath)
{
	struct stat buffer;
	int ret = stat(pPath.c_str(), &buffer);
	if (ret != 0)
		return false;

	// if (ENOENT == errno)
	//	return false;

	if (S_ISREG(buffer.st_mode))
		return true;

	return false;
}

// trim the last filename 
// true:   dir/
// false:  dir/subdir    dir/file   file
bool cUnpackFile::splitDirAndName(const string &str, string& dir)
{
	unsigned pos = str.find_last_of('/');
	if (pos != std::string::npos)
	{
		dir = str.substr(0, pos);
		if (pos == str.length() -1)
			return true;
		return false;
	}
	
	pos = str.find_last_of('\\');
	if (pos != std::string::npos)
	{
		dir = str.substr(0, pos);
		if (pos == str.length() -1)
			return true;
		return false;
	}

	return false;
}

bool writeToFile(const string & filepath, unzFile unZipDir)
{
	FILE *pFile  = fopen(filepath.c_str(), "wb");
	if (!pFile)
	{
		printf("无法打开输出文件 %s \n", filepath);
		return false;
	}
	int nReadBytes = 0;
	char buffer[4096 * 10];

	do 
	{
		nReadBytes = unzReadCurrentFile(unZipDir, buffer, 4096 * 10);
		if (nReadBytes > 0)
			fwrite(buffer, nReadBytes, 1, pFile);

	}while (nReadBytes > 0);
	
	fclose(pFile);

	return true;
}

void cUnpackFile::CreateDirFromZip(const string & dirName, const string & zipFileName)
{
	bool slashFlag = true;
	unzFile unZipDir = unzOpen(zipFileName.c_str());

	// remove last '/' 
	string dirBase = dirName;
	if (dirBase.length() > 0 && dirBase.at(dirBase.length() -1) == '/')
		dirBase = dirName.substr(0, dirName.length() -1);

	if (PathUtil::isFile(dirName))
	{
		printf("path is a file, 无法解压zip文件!");
		return;
	}

	if (0 != PathUtil::createDir(dirName))
	{
		printf("cant't create dir %s  \n", dirName.c_str());
		return;
	}

	int nResult = unzGoToFirstFile(unZipDir);

	char szCurrentFile[260];
	unz_file_info unZipFileInfo;

	while (nResult == UNZ_OK)
	{
		
		unzGetCurrentFileInfo(unZipDir, &unZipFileInfo, szCurrentFile, sizeof(szCurrentFile), NULL, 0, NULL, 0);

		std::string filePath = std::string(szCurrentFile);
		std::string dirPart = "";
		std::string dirCurrent = "";
		bool bDir = this->splitDirAndName(szCurrentFile, dirPart);
		// path have dirs
		if (dirPart.length() > 0)
		{
			
			dirCurrent  = dirBase + "/" + dirPart;

			int ret = PathUtil::createDir(dirCurrent);
			if(ret != 0)
			{
				break;
			}

			if (true == bDir)
			{
				nResult = unzGoToNextFile(unZipDir);
				continue; //文件夹项
			}
		}

		//int size = unZipFileInfo.uncompressed_size;

		if (UNZ_OK == unzOpenCurrentFilePassword(unZipDir, NULL))
		{
			string filePos = dirBase +  "/" + filePath;
			writeToFile(filePos, unZipDir);
			unzCloseCurrentFile(unZipDir);
		}

	
		nResult = unzGoToNextFile(unZipDir);
	}
	unzClose(unZipDir);
}

void cUnpackFile::CreateFileFromZip(const string &fName, const string & zipFileName)
{
	bool slashFlag = true;
	unzFile unZipDir = unzOpen(zipFileName.c_str());

	if (unZipDir == NULL)
	{
		printf("无法解压zip文件!");
		return;
	}

	int nResult = unzGoToFirstFile(unZipDir);
	char szCurrentFile[260];
	unz_file_info unZipFileInfo;

	if (nResult == UNZ_OK)
	{
		
		unzGetCurrentFileInfo(unZipDir, &unZipFileInfo, szCurrentFile, sizeof(szCurrentFile), NULL, 0, NULL, 0);

		//int size = unZipFileInfo.uncompressed_size;
	
		if (UNZ_OK == unzOpenCurrentFilePassword(unZipDir, NULL))
		{
			writeToFile(fName, unZipDir);
			unzCloseCurrentFile(unZipDir);
		}
	
	}
	unzClose(unZipDir);
}

cUnpackFile::cUnpackFile()
{
}

cUnpackFile::~cUnpackFile()
{
}

使用的时候,需要将minizip拷贝到当前目录,编译即可;

参考的文档:http://t.csdn.cn/aCfC6

该帖子实现了windows版本的功能;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值