声明:本篇文章部分内容转自互联网,因为这些代码不能直接运行,本人对其略有修改。
C++使用zlib压缩和解压缩文件
http://download.csdn.net/download/yanghongche/5029259
C#使用
ICSharpCode.SharpZipLib.dll压缩解压缩
http://www.cnblogs.com/xuanye/archive/2011/10/19/2217211.html
C++开发工具使用的是VC++6.0,C#开发工具使用的是VS2012。
(一)、C++编写生成解压缩带有密码的zip压缩文件(使用zlib)的动态链接库dll
一、第一步:创建动态链接库工程
(二)、c#编写的解压带有密码的压缩文件
1. 新建--工程--win32 dynamic-link library,输入工程名字unzip,确定,一个简单的dll工程,确定,确定。
2. 新建--文件--c/c++ header file--文件名unzip,确定。
该头文件里写以下代码:
#include "afx.h"extern "C" _declspec(dllexport) int __stdcall UnzipFile(char* FilePath, char* TmpPath, char* Psd);
3. stdafx.h头文件里却掉以下代码:
#include <windows.h>
若不去掉会报一下错误:fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>
4. unzip.cpp里写入以下代码:
// unzip.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "unzip.h"
#include<iostream>
#include<string>
#include "Shlwapi.h"
using std::string;
using namespace std;
#include "zlib\unzip.h"
#include "zlib\zlib.h"
#include "zlib\zip.h"
#pragma comment( lib, "zlib.lib" ) // 将静态库引用进来
#pragma comment( lib, "minizip.lib" )
#pragma comment( lib, "Shlwapi.lib" )
#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 102400 // 从zip文件中一次读取的最大缓冲值
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
// 在磁盘中创建路径strPath
void CreateFilePath(CString strPath)
{
int nPos;
CString strFolder("");
for (nPos = 0; nPos != -1; nPos = strPath.Find("\\"))
{
nPos = strPath.Find("\\");
strFolder += strPath.Left(nPos);
if (PathFileExists(strFolder)!=1)
{
CreateDirectory(strFolder, NULL);
}
strPath = strPath.Mid(nPos+1);
strFolder += "\\";
}
}
// 格式化路径,把'/'改成'\\'
void FormatDirectorys( LPSTR lpszDirectorys )
{
if( lpszDirectorys!= NULL )
{
int i=0;
while( lpszDirectorys[ i ] != _T('\0') )
{
if( lpszDirectorys[ i ] == _T('/') )
{
lpszDirectorys[ i ] = _T('\\');
}
i++;
}
}
}
//函数名称:UnzipFile
//函数功能:解压zip文件
//输入参数:strFilePath 带解压zip文件的路径+名称
// strTmpPath 解压到这个路径下
// strPsd 密码
//返 回 值:参考ConfigInfo.h
int __stdcall UnzipFile(char* FilePath, char* TmpPath, char* Psd)
{
//char*转换为CString
CString strFilePath;
strFilePath.Format("%s",FilePath);
CString strTmpPath;
strTmpPath.Format("%s",TmpPath);
CString strPsd;
strPsd.Format("%s",Psd);
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;
long vfilesize;
long vlastsize;
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);
vfilesize=p_fInfo->uncompressed_size;
strZipFName = szZipFName;
strDiskFile = strTmpPath + CString(_T("\\")) + strZipFName;
HANDLE hFile = CreateFile(strDiskFile, GENERIC_WRITE, // 对文件进行只写访问
0, // 独占对文件的访问
NULL, OPEN_ALWAYS, // 打开已有文件,若存在则直接打开,否则创建新文件
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;
}
}
long count=0;
vlastsize = vfilesize;
while(TRUE)
{
nNum = 0;
count++;
memset(szReadBuf, 0, MAX_BUFSIZE);
if(vlastsize>=MAX_BUFSIZE)
{
nNum = unzReadCurrentFile(uf, szReadBuf, MAX_BUFSIZE); // 从zip中读数据
}else{
nNum = unzReadCurrentFile(uf, szReadBuf, vlastsize); // 从zip中读数据
}
if (nNum < 0)
{
unzCloseCurrentFile(uf);
CloseHandle(hFile);
return ZIP_READFILE_ERR;
}
else if (nNum == 0)
{
unzCloseCurrentFile(uf);
CloseHandle(hFile);
break;
}
else
{
if(vlastsize>=MAX_BUFSIZE)
{
if (!WriteFile(hFile, szReadBuf, MAX_BUFSIZE, &dWrite, NULL))// 往本地磁盘写数据
{
unzCloseCurrentFile(uf);
CloseHandle(hFile);
return (GetLastError());
}
}else{
if (!WriteFile(hFile, szReadBuf, vlastsize, &dWrite, NULL))// 往本地磁盘写数据
{
unzCloseCurrentFile(uf);
CloseHandle(hFile);
return (GetLastError());
}
}
}
if(vlastsize>=MAX_BUFSIZE)
{
vlastsize = vlastsize - MAX_BUFSIZE;
}else{
vlastsize = vlastsize;
}
}
break;
}
}
unzGoToNextFile(uf);
}
if (uf)
unzClose(uf);
return -1;
}
<div><div style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; FONT: medium Tahoma; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"> </div></div>
5. 这时候编译会报一些错误。
6. 将zlib文件夹放到工程目录下。不放会报一下错误:Cannot open include file: 'zlib\unzip.h': No such file or directory。
7. 这时编译会报一下错误:
LIBCMTD.lib(crt0init.obj) : warning LNK4098: defaultlib "msvcrt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library
解决办法:
project -- settings-- 连接 --工程选项下 增加 /NODEFAULTLIB:msvcrt.lib 字符串。
8. project -- settings-- c/c++ --code generation -- use runtime library --debug multithreaded dll
预处理器 下 预处理器定义 去掉_USERDLL 增加 _AFXDLL
在c/c++下的工程选项里 去掉 /GZ 或者 /GD
9.创建def文件
新建--文件--文本文件 增加代码:
LIBRARY "unzip"
EXPORTS
UnzipFile @1
EXPORTS
UnzipFile @1
进入工程目录下,修改扩展名txt改为def
在vc++6.0面板上的unzip files 右键 -- 添加文件到工程-- 选择def类型的文件--选择unzip 确定。
10. build构建动态链接库。就可以用了。
11.PB8调用unzip.dll
引用:
function long UnzipFile(string FilePath,string TmpPath,string Psd) library 'unzip.dll'
代码:
string ls_src,ls_dst
ls_src='F:\\131\\15\\150010\\1\\131.zip'
ls_dst='F:\\131\\15\\150010\\1\\3\\'
string ls_psd
ls_psd = 'mima'
long ret
ret = UnzipFile(ls_src,ls_dst,ls_psd)
messagebox('','解压完毕!'+string(ret))
ls_src='F:\\131\\15\\150010\\1\\131.zip'
ls_dst='F:\\131\\15\\150010\\1\\3\\'
string ls_psd
ls_psd = 'mima'
long ret
ret = UnzipFile(ls_src,ls_dst,ls_psd)
messagebox('','解压完毕!'+string(ret))
(二)、c#编写的解压带有密码的压缩文件
以下是dll项目Unzip.cs里的内容,项目要引用
ICSharpCode.SharpZipLib.dll文件
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
namespace unzipfile
{
[Guid("a1462ebc-1f88-4d2a-b677-48f61b834907")]
public class Unzip
{
/// <summary>
/// 实现解压操作
/// </summary>
/// <param name="zipfilename"> 要解压文件Zip(物理路径) </param>
/// <param name="UnZipDir"> 解压目的路径(物理路径) </param>
/// <param name="password"> 解压密码</param>
/// <returns> 异常信息</returns>
public string UnMakeZipFile(string zipfilename, string UnZipDir, string password)
{
//判断待解压文件路径
if (!File .Exists(zipfilename))
{
File.Delete(UnZipDir);
return "待解压文件路径不存在!" ;
}
//创建ZipInputStream
ZipInputStream newinStream = new ZipInputStream( File.OpenRead(zipfilename));
//判断Password
if (password != null && password.Length > 0)
{
newinStream.Password = password;
}
//执行解压操作
try
{
ZipEntry theEntry;
//获取Zip中单个File
while ((theEntry = newinStream.GetNextEntry()) != null)
{
//判断目的路径
if (!Directory .Exists(UnZipDir))
{
Directory.CreateDirectory(UnZipDir);//创建目的目录
}
//获得目的目录信息
string Driectoryname = Path .GetDirectoryName(UnZipDir);
string pathname = Path .GetDirectoryName(theEntry.Name);//获得子级目录
string filename = Path .GetFileName(theEntry.Name);//获得子集文件名
//处理文件盘符问题
pathname = pathname.Replace( ":", "$" );//处理当前压缩出现盘符问题
Driectoryname = Driectoryname + "\\" + pathname;
//创建
Directory.CreateDirectory(Driectoryname);
//解压指定子目录
if (filename != string .Empty)
{
FileStream newstream = File .Create(Driectoryname + "\\" + filename);
int size = 2048;
byte[] newbyte = new byte[size];
while (true )
{
size = newinStream.Read(newbyte, 0, newbyte.Length);
if (size > 0)
{
//写入数据
newstream.Write(newbyte, 0, size);
}
else
{
break;
}
}
newstream.Close();
}
}
newinStream.Close();
}
catch (Exception se)
{
return se.Message.ToString();
}
finally
{
newinStream.Close();
}
return "" ;
}
}
}
2.需要使用vs2012开发人员命令提示工具找到dll所在目录 执行 regasm unzipfile.dll /tlb:unzipfile.tlb
3. PB程序调用:
增加一个实例变量
OLEObject unzip
在窗体的Open()事件里面写下以下代码
unzip= Create OLEObject
unzip.ConnectToNewObject("unzipfile.Unzip")
"unzipfile" 是你C#写的DLL的命名空间的名称
"Unzip"是你的DLL的类名称.别搞错了.
PB程序调用:
string ls_src,ls_dst
ls_src='F:\\13215001010029.zip'
ls_dst='F:\\13215001010029\\'
string ls_psd
ls_psd = 'aaaa'
string ls_ret
ls_ret = unzipf(ls_src,ls_dst,ls_psd)
messagebox('','解压完毕!'+ls_ret)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
namespace unzipfile
{
[Guid("a1462ebc-1f88-4d2a-b677-48f61b834907")]
public class Unzip
{
/// <summary>
/// 实现解压操作
/// </summary>
/// <param name="zipfilename"> 要解压文件Zip(物理路径) </param>
/// <param name="UnZipDir"> 解压目的路径(物理路径) </param>
/// <param name="password"> 解压密码</param>
/// <returns> 异常信息</returns>
public string UnMakeZipFile(string zipfilename, string UnZipDir, string password)
{
//判断待解压文件路径
if (!File .Exists(zipfilename))
{
File.Delete(UnZipDir);
return "待解压文件路径不存在!" ;
}
//创建ZipInputStream
ZipInputStream newinStream = new ZipInputStream( File.OpenRead(zipfilename));
//判断Password
if (password != null && password.Length > 0)
{
newinStream.Password = password;
}
//执行解压操作
try
{
ZipEntry theEntry;
//获取Zip中单个File
while ((theEntry = newinStream.GetNextEntry()) != null)
{
//判断目的路径
if (!Directory .Exists(UnZipDir))
{
Directory.CreateDirectory(UnZipDir);//创建目的目录
}
//获得目的目录信息
string Driectoryname = Path .GetDirectoryName(UnZipDir);
string pathname = Path .GetDirectoryName(theEntry.Name);//获得子级目录
string filename = Path .GetFileName(theEntry.Name);//获得子集文件名
//处理文件盘符问题
pathname = pathname.Replace( ":", "$" );//处理当前压缩出现盘符问题
Driectoryname = Driectoryname + "\\" + pathname;
//创建
Directory.CreateDirectory(Driectoryname);
//解压指定子目录
if (filename != string .Empty)
{
FileStream newstream = File .Create(Driectoryname + "\\" + filename);
int size = 2048;
byte[] newbyte = new byte[size];
while (true )
{
size = newinStream.Read(newbyte, 0, newbyte.Length);
if (size > 0)
{
//写入数据
newstream.Write(newbyte, 0, size);
}
else
{
break;
}
}
newstream.Close();
}
}
newinStream.Close();
}
catch (Exception se)
{
return se.Message.ToString();
}
finally
{
newinStream.Close();
}
return "" ;
}
}
}
2.需要使用vs2012开发人员命令提示工具找到dll所在目录 执行 regasm unzipfile.dll /tlb:unzipfile.tlb
3. PB程序调用:
增加一个实例变量
OLEObject unzip
在窗体的Open()事件里面写下以下代码
unzip= Create OLEObject
unzip.ConnectToNewObject("unzipfile.Unzip")
"unzipfile" 是你C#写的DLL的命名空间的名称
"Unzip"是你的DLL的类名称.别搞错了.
PB程序调用:
string ls_src,ls_dst
ls_src='F:\\13215001010029.zip'
ls_dst='F:\\13215001010029\\'
string ls_psd
ls_psd = 'aaaa'
string ls_ret
ls_ret = unzipf(ls_src,ls_dst,ls_psd)
messagebox('','解压完毕!'+ls_ret)