使用zlib压缩解压缩文件

文章转载地址http://blog.sina.com.cn/s/blog_53bd4e3301000a8b.html



zlib是一套公开源代码的压缩,解压缩的函数库,提供了很多文件操作的方法,但是他不是一套类库,所以有兴趣的人都可以把他进行封装,实现自己的类库,和更高层的接口。
具体的介绍可以参考http://www.gzip.org/zlib/主页,这里有详细介绍。
    这里简单实现了zlib的最简单的用法,压缩一个文件,通过使用文件映射来实现的。
    包含头文件 zlib.h 和 zconf.h 和 zlib.lib
在stdafx.h 中加入:
#ifdef _DEBUG
#pragma comment(lib,"zlibd.lib")
#else
#pragma comment(lib,"zlib.lib")
#endif
#include "zlib.h"
#include "zconf.h"
压缩代码:

 HANDLE hFile, hFileToWrite;
 CString strFilePath;
 m_ctrEdit.GetWindowText(strFilePath);
 
 //打开要进行压缩的文件
 hFile = CreateFile(strFilePath, // file name
  GENERIC_READ, // open for reading
  FILE_SHARE_READ, // share for reading
  NULL, // no security
  OPEN_EXISTING, // existing file only
  FILE_ATTRIBUTE_NORMAL, // normal file
  NULL); // no attr. template
 
 if (hFile == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox("Could not open file to read"); // process error
  return;
 }
 
 HANDLE hMapFile, hMapFileToWrite;
 
 //创建一个文件映射
 hMapFile = CreateFileMapping(hFile, // Current file handle.
  NULL, // Default security.
  PAGE_READONLY, // Read/write permission.
  0, // Max. object size.
  0, // Size of hFile.
  "ZipTestMappingObjectForRead"); // Name of mapping object.
 
 if (hMapFile == NULL)
 {
  AfxMessageBox("Could not create file mapping object");
  return;
 }
 
 LPVOID lpMapAddress, lpMapAddressToWrite;
 
 //创建一个文件映射的视图用来作为source
 lpMapAddress = MapViewOfFile(hMapFile, // Handle to mapping object.
  FILE_MAP_READ, // Read/write permission
  0, // Max. object size.
  0, // Size of hFile.
  0); // Map entire file.
 
 if (lpMapAddress == NULL)
 {
  AfxMessageBox("Could not map view of file");
  return;
 }
 
 //
 DWORD dwFileLength,dwFileLengthToWrite;
 dwFileLength = GetFileSize(hFile, NULL);
 m_dwSourceFileLength = dwFileLength;
 //因为压缩函数的输出缓冲必须比输入大0.1% + 12 然后一个DWORD用来保存压缩前的大小,
 // 解压缩的时候用,当然还可以保存更多的信息,这里用不到
 dwFileLengthToWrite = (double)dwFileLength*1.001 + 12 + sizeof(DWORD);
 
 //以下是创建一个文件,用来保存压缩后的文件
 hFileToWrite = CreateFile("demoFile.rar", // demoFile.rar
  GENERIC_WRITE|GENERIC_READ, // open for writing
  0, // do not share
  NULL, // no security
  CREATE_ALWAYS, // overwrite existing
  FILE_ATTRIBUTE_NORMAL , // normal file
  NULL); // no attr. template
 
 if (hFileToWrite == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox("Could not open file to write"); // process error
  return;
 }
 
 hMapFileToWrite = CreateFileMapping(hFileToWrite, // Current file handle.
  NULL, // Default security.
  PAGE_READWRITE, // Read/write permission.
  0, // Max. object size.
  dwFileLengthToWrite, // Size of hFile.
  "ZipTestMappingObjectForWrite"); // Name of mapping object.
 
 if (hMapFileToWrite == NULL)
 {
  AfxMessageBox("Could not create file mapping object for write");
  return;
 }
 
 lpMapAddressToWrite = MapViewOfFile(hMapFileToWrite, // Handle to mapping object.
  FILE_MAP_WRITE, // Read/write permission
  0, // Max. object size.
  0, // Size of hFile.
  0); // Map entire file.
 
 if (lpMapAddressToWrite == NULL)
 {
  AfxMessageBox("Could not map view of file");
  return;
 }
 
 //这里是将压缩前的大小保存在文件的第一个DWORD里面
 LPVOID pBuf = lpMapAddressToWrite;
 (*(DWORD*)pBuf) = dwFileLength;
 pBuf = (DWORD*)pBuf + 1;
 
 
 //
 
 //这里就是最重要的,zlib里面提供的一个方法,将源缓存的数据压缩至目的缓存
 //原形如下:
 //int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
 //参数destLen返回实际压缩后的文件大小。
 compress((Bytef*)pBuf,&dwFileLengthToWrite, (Bytef*)lpMapAddress, dwFileLength);
 
 //
 
 UnmapViewOfFile(lpMapAddress);
 CloseHandle(hMapFile);
 CloseHandle(hFile);
 
 UnmapViewOfFile(lpMapAddressToWrite);
 CloseHandle(hMapFileToWrite);
 //这里将文件大小重新设置一下
 SetFilePointer(hFileToWrite,dwFileLengthToWrite + sizeof(DWORD) ,NULL,FILE_BEGIN);
 SetEndOfFile(hFileToWrite);
 CloseHandle(hFileToWrite);

解压缩的方法其他地方都一样,不同的就是使用方法是uncompress而不是compress
原形如下:

int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
解压缩代码如下:

 HANDLE hFile, hFileToWrite;
 CString strFilePath;
 m_ctrEdit.GetWindowText(strFilePath);
 
 //打开要进行解压缩的文件
 hFile = CreateFile(strFilePath, // file name
  GENERIC_READ, // open for reading
  FILE_SHARE_READ, // share for reading
  NULL, // no security
  OPEN_EXISTING, // existing file only
  FILE_ATTRIBUTE_NORMAL, // normal file
  NULL); // no attr. template
 
 if (hFile == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox("Could not open file to read"); // process error
  return;
 }
 
 HANDLE hMapFile, hMapFileToWrite;
 
 //创建一个文件映射
 hMapFile = CreateFileMapping(hFile, // Current file handle.
  NULL, // Default security.
  PAGE_READONLY, // Read/write permission.
  0, // Max. object size.
  0, // Size of hFile.
  "ZipTestMappingObjectForRead"); // Name of mapping object.
 
 if (hMapFile == NULL)
 {
  AfxMessageBox("Could not create file mapping object");
  return;
 }
 
 LPVOID lpMapAddress, lpMapAddressToWrite;
 
 //创建一个文件映射的视图用来作为source
 lpMapAddress = MapViewOfFile(hMapFile, // Handle to mapping object.
  FILE_MAP_READ, // Read/write permission
  0, // Max. object size.
  0, // Size of hFile.
  0); // Map entire file.
 
 if (lpMapAddress == NULL)
 {
  AfxMessageBox("Could not map view of file");
  return;
 }
 
 //
 DWORD dwFileLength,dwFileLengthToWrite;
 dwFileLength = GetFileSize(hFile, NULL) - sizeof(DWORD);
 //因为压缩函数的输出缓冲必须比输入大0.1% + 12 然后一个DWORD用来保存压缩前的大小,
 // 解压缩的时候用,当然还可以保存更多的信息,这里用不到
// dwFileLengthToWrite = (double)dwFileLength*1.001 + 12 + sizeof(DWORD);
 dwFileLengthToWrite = (*(DWORD*)lpMapAddress);

 LPVOID pSourceBuf = lpMapAddress;
 pSourceBuf = (DWORD*)pSourceBuf + 1;
 
 //以下是创建一个文件,用来保存压缩后的文件
 hFileToWrite = CreateFile("demoFile.pdf", // create demo.gz
  GENERIC_WRITE|GENERIC_READ, // open for writing
  0, // do not share
  NULL, // no security
  CREATE_ALWAYS, // overwrite existing
  FILE_ATTRIBUTE_NORMAL , // normal file
  NULL); // no attr. template
 
 if (hFileToWrite == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox("Could not open file to write"); // process error
  return;
 }
 
 hMapFileToWrite = CreateFileMapping(hFileToWrite, // Current file handle.
  NULL, // Default security.
  PAGE_READWRITE, // Read/write permission.
  0, // Max. object size.
  dwFileLengthToWrite, // Size of hFile.
  "ZipTestMappingObjectForWrite"); // Name of mapping object.
 
 if (hMapFileToWrite == NULL)
 {
  AfxMessageBox("Could not create file mapping object for write");
  return;
 }
 
 lpMapAddressToWrite = MapViewOfFile(hMapFileToWrite, // Handle to mapping object.
  FILE_MAP_WRITE, // Read/write permission
  0, // Max. object size.
  0, // Size of hFile.
  0); // Map entire file.
 
 if (lpMapAddressToWrite == NULL)
 {
  AfxMessageBox("Could not map view of file");
  return;
 }
 
 //这里是将压缩前的大小保存在文件的第一个DWORD里面
 LPVOID pBuf = lpMapAddressToWrite;
 
 
 //
 
 //这里就是最重要的,zlib里面提供的一个方法,将源缓存的数据压缩至目的缓存
 //原形如下:
 //int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
 //参数destLen返回实际压缩后的文件大小。
 uncompress((Bytef*)pBuf,&dwFileLengthToWrite, (Bytef*)pSourceBuf, dwFileLength);
 
 //
 
 UnmapViewOfFile(lpMapAddress);
 CloseHandle(hMapFile);
 CloseHandle(hFile);
 
 UnmapViewOfFile(lpMapAddressToWrite);
 CloseHandle(hMapFileToWrite);
 //这里将文件大小重新设置一下
 SetFilePointer(hFileToWrite,dwFileLengthToWrite ,NULL,FILE_BEGIN);
 SetEndOfFile(hFileToWrite);
 CloseHandle(hFileToWrite);

以上代码通过测试,如果有疑问可以联系dawn2004cn@163.com


备注:

以上是将一个文件进行压缩。在压缩文件的开头保存了原始文件的大小。若要保存一个文件的大小和文件名字等信息,可以定义一个结构体:(以下代码为自己根据上面的例子进行了改进,经验证,可以通过)

struct fileInfo
{
DWORD fileLength;//保存文件的大小
//char buf[100];
char *buf;//保存文件的名字的字符串指针


};

压缩文件函数如下:

void CcompressDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(TRUE);
CString filePath;
CString fileSelectName;
if(dlg.DoModal() == IDOK)
{
filePath=dlg.GetPathName();
fileSelectName=dlg.GetFileName();

}


//open the file (wants to compress)
HANDLE  hFile, hFileToWrite;
hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 


if (hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("Could not open file to read"), MB_OK, NULL); // process error
return;
}




//创建文件映射
HANDLE hMapFile, hMapFileToWrite;
hMapFile=CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, _T("ZipTest"));
if(hMapFile == NULL)
{
AfxMessageBox(_T("couldn't create file mapping object"), MB_OK, NULL);
return;
}




//创建一个文件映射的视图用来作为source
LPVOID lpMapAddress, lpMapAddressToWrite;
lpMapAddress=MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);


if(lpMapAddress == NULL)
{
AfxMessageBox(_T("couldn't map view of file"), MB_OK, NULL);
return;
}


DWORD dwFileLength, dwFileLengthToWrite;
dwFileLength=GetFileSize(hFile, NULL);
// m_dwSourceFileLength=dwFileLength;


//压缩函数的输出缓冲必须比输入大于0.1% + 12, 然后一个DWORD用来保存压缩前的文件大小
//dwFileLengthToWrite=(double)dwFileLength*1.01 + 12 + sizeof(DWORD);
dwFileLengthToWrite=(double)dwFileLength*1.01 + 12 + sizeof(fileInfo);


//创建一个文件,用来保存压缩后的文件
hFileToWrite = CreateFile(_T("demoFile.rar"),GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);


if(hFileToWrite == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("couldn't open file to write"), MB_OK, NULL);
return;
}


hMapFileToWrite = CreateFileMapping(hFileToWrite, NULL, PAGE_READWRITE, 0, dwFileLengthToWrite, _T("zipTest"));
if(hMapFileToWrite == NULL)
{
AfxMessageBox(_T("couldn't create file mapping object for write"), MB_OK, NULL);
return;
 
}


lpMapAddressToWrite = MapViewOfFile(hMapFileToWrite, FILE_MAP_WRITE, 0, 0, 0);


if(lpMapAddressToWrite == NULL)
{
AfxMessageBox(_T("couldn't map view of file"), MB_OK, NULL);
return;
 
}






// new methond
fileInfo tmp;
tmp.fileLength = dwFileLength;
//tmpFileName
// tmp.buf = (LPSTR)(LPCTSTR)filePath;
long len=fileSelectName.GetAllocLength() + 1;
int len1 =fileSelectName.GetLength() + 1;
 tmp.buf = new char [len];


//CString  转换为char * 
 memset(tmp.buf, 0, len);
 WideCharToMultiByte(CP_ACP, 0, fileSelectName, -1, tmp.buf, len, NULL, NULL);
// strcpy(tmp.buf, (LPSTR)(LPCTSTR)filePath);


//将压缩前的大小保存在文件的第一个DWORD里面
LPVOID pBuf = lpMapAddressToWrite;
// (*(DWORD *)pBuf) = dwFileLength;


(*(fileInfo *)pBuf) = tmp;
// pBuf = (DWORD *)pBuf + 1;
pBuf = (fileInfo *)pBuf + 1;


compress((Bytef *)pBuf, &dwFileLengthToWrite, (Bytef *)lpMapAddress, dwFileLength);


UnmapViewOfFile(lpMapAddress);
CloseHandle(hMapFile);
CloseHandle(hFile);


UnmapViewOfFile(lpMapAddressToWrite);
CloseHandle(hMapFileToWrite);


//重设文件大小
SetFilePointer(hFileToWrite, dwFileLengthToWrite + sizeof(DWORD), NULL, FILE_BEGIN);
SetEndOfFile(hFileToWrite);
CloseHandle(hFileToWrite);


}


相对应的解压缩函数:

void CcompressDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CString strFilePath;
CFileDialog dlg(TRUE);
if(dlg.DoModal() == IDOK)
{
strFilePath=dlg.GetPathName();

}


// uncompress();


HANDLE hFile, hFileToWrite;
// CString strFilePath;
 //m_ctrEdit.GetWindowText(strFilePath);
 
 //打开要进行解压缩的文件
 hFile = CreateFile(strFilePath, // file name
  GENERIC_READ, // open for reading
  FILE_SHARE_READ, // share for reading
  NULL, // no security
  OPEN_EXISTING, // existing file only
  FILE_ATTRIBUTE_NORMAL, // normal file
  NULL); // no attr. template
 
 if (hFile == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox(_T("Could not open file to read"), MB_OK, NULL); // process error
  return;
 }
 
 HANDLE hMapFile, hMapFileToWrite;
 
 //创建一个文件映射
 hMapFile = CreateFileMapping(hFile, // Current file handle.
  NULL, // Default security.
  PAGE_READONLY, // Read/write permission.
  0, // Max. object size.
  0, // Size of hFile.
  _T("ZipTestMappingObjectForRead")); // Name of mapping object.
 
 if (hMapFile == NULL)
 {
  AfxMessageBox(_T("Could not create file mapping object"), MB_OK, NULL);
  return;
 }
 
 LPVOID lpMapAddress, lpMapAddressToWrite;
 
 //创建一个文件映射的视图用来作为source
 lpMapAddress = MapViewOfFile(hMapFile, // Handle to mapping object.
  FILE_MAP_READ, // Read/write permission
  0, // Max. object size.
  0, // Size of hFile.
  0); // Map entire file.
 
 if (lpMapAddress == NULL)
 {
  AfxMessageBox(_T("Could not map view of file"), MB_OK, NULL);
  return;
 }
 
 //
 DWORD dwFileLength,dwFileLengthToWrite;
 //dwFileLength = GetFileSize(hFile, NULL) - sizeof(DWORD);
 dwFileLength = GetFileSize(hFile, NULL) - sizeof(fileInfo);
 //因为压缩函数的输出缓冲必须比输入大0.1% + 12 然后一个DWORD用来保存压缩前的大小,
 // 解压缩的时候用,当然还可以保存更多的信息,这里用不到
// dwFileLengthToWrite = (double)dwFileLength*1.001 + 12 + sizeof(DWORD);//原始
 //dwFileLengthToWrite = (*(DWORD*)lpMapAddress);
 fileInfo tmp;
 tmp=(*(fileInfo*)lpMapAddress);
 dwFileLengthToWrite = tmp.fileLength;
 char *tmpName=tmp.buf;


//char  * 转换为LPCWSTR     LPCWSTR实际上也是CONST WCHAR *类型
 WCHAR tmpFileName[256];
 //CString tmpFileName;
 MultiByteToWideChar(CP_ACP,0,tmpName,strlen(tmpName)+1,tmpFileName,  
    sizeof(tmpFileName)/sizeof(tmpFileName[0]));  






 LPVOID pSourceBuf = lpMapAddress;
// pSourceBuf = (DWORD*)pSourceBuf + 1;
 pSourceBuf = (fileInfo*)pSourceBuf + 1;
 








 //以下是创建一个文件,用来保存压缩后的文件
// hFileToWrite = CreateFile(_T("demoFile.pdf"),
 hFileToWrite = CreateFile(tmpFileName, // create demo.gz
  GENERIC_WRITE|GENERIC_READ, // open for writing
  0, // do not share
  NULL, // no security
  CREATE_ALWAYS, // overwrite existing
  FILE_ATTRIBUTE_NORMAL , // normal file
  NULL); // no attr. template
 
 if (hFileToWrite == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox(_T("Could not open file to write"), MB_OK, NULL); // process error
  return;
 }
 
 hMapFileToWrite = CreateFileMapping(hFileToWrite, // Current file handle.
  NULL, // Default security.
  PAGE_READWRITE, // Read/write permission.
  0, // Max. object size.
  dwFileLengthToWrite, // Size of hFile.
  _T("ZipTestMappingObjectForWrite")); // Name of mapping object.
 
 if (hMapFileToWrite == NULL)
 {
  AfxMessageBox(_T("Could not create file mapping object for write"), MB_OK, NULL);
  return;
 }
 
 lpMapAddressToWrite = MapViewOfFile(hMapFileToWrite, // Handle to mapping object.
  FILE_MAP_WRITE, // Read/write permission
  0, // Max. object size.
  0, // Size of hFile.
  0); // Map entire file.
 
 if (lpMapAddressToWrite == NULL)
 {
  AfxMessageBox(_T("Could not map view of file"), MB_OK, NULL);
  return;
 }
 
 //这里是将压缩前的大小保存在文件的第一个DWORD里面
 LPVOID pBuf = lpMapAddressToWrite;
 
 
 //
 
 //这里就是最重要的,zlib里面提供的一个方法,将源缓存的数据压缩至目的缓存
 //原形如下:
 //int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
 //参数destLen返回实际压缩后的文件大小。
 uncompress((Bytef*)pBuf,&dwFileLengthToWrite, (Bytef*)pSourceBuf, dwFileLength);
 
 //
 
 UnmapViewOfFile(lpMapAddress);
 CloseHandle(hMapFile);
 CloseHandle(hFile);
 
 UnmapViewOfFile(lpMapAddressToWrite);
 CloseHandle(hMapFileToWrite);
 //这里将文件大小重新设置一下
 SetFilePointer(hFileToWrite,dwFileLengthToWrite ,NULL,FILE_BEGIN);
 SetEndOfFile(hFileToWrite);
 CloseHandle(hFileToWrite);


}


类型之间的转换:  http://blog.youkuaiyun.com/zhouxuguang236/article/details/8761497


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值