文章转载地址http://blog.sina.com.cn/s/blog_53bd4e3301000a8b.html
zlib是一套公开源代码的压缩,解压缩的函数库,提供了很多文件操作的方法,但是他不是一套类库,所以有兴趣的人都可以把他进行封装,实现自己的类库,和更高层的接口。
具体的介绍可以参考http://www.gzip.org/zlib/主页,这里有详细介绍。
在stdafx.h 中加入:
#ifdef _DEBUG
#pragma comment(lib,"zlibd.lib")
#else
#pragma comment(lib,"zlib.lib")
#endif
#include "zlib.h"
#include "zconf.h"
压缩代码:
解压缩的方法其他地方都一样,不同的就是使用方法是uncompress而不是compress
原形如下:
int uncompress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
解压缩代码如下:
//
以上代码通过测试,如果有疑问可以联系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