zlib_utils.h
#pragma once
#include <Windows.h>
#include <tchar.h>
// 压缩文件
BOOL CompressFile(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
);
// 解压缩文件
BOOL UncompressFile(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
);
// 压缩文件
BOOL compress_file(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
);
// 解压缩文件
BOOL uncompress_file(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
);
zlib_utils.c
#include "zlib_utils.h"
#include <errno.h>
#include <malloc.h>
#define ZLIB_WINAPI
#ifdef __cplusplus
extern "C"
{
#endif
#include "zlib.h"
#ifdef __cplusplus
}
#endif
// 数据块标识
#define ZDF_HEADER_FLAG (0x0046445A)
// 单次压缩数据块大小
#define ZDF_BLOCK_SIZE (1024 * 1024 * 4)
// 数据块信息结构
typedef struct _ZDF_HEADER
{
DWORD dwFlag; //块标识
DWORD dwCheckSum; //块校验码
DWORD dwDataSize; //压缩后数据大小
DWORD dwRawDataSize; //压缩前数据大小
}ZDF_HEADER;
BOOL CompressFile(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
)
{
HANDLE hDestFile = INVALID_HANDLE_VALUE;
HANDLE hSrcFile = INVALID_HANDLE_VALUE;
LPVOID lpOutputBuf = NULL;
LPVOID lpInputBuf = NULL;
BOOL fResult = FALSE;
do
{
DWORD dwInputBufSize = ZDF_BLOCK_SIZE; // 读取块大小
DWORD dwOutputBufSize = dwInputBufSize * 2; // 输出块设为输入块2倍
// 分配缓冲
lpInputBuf = HeapAlloc(GetProcessHeap(), 0, dwInputBufSize);
if (NULL == lpInputBuf)
{
break;
}
// 分配缓冲
lpOutputBuf = HeapAlloc(GetProcessHeap(), 0, dwOutputBufSize);
if (NULL == lpOutputBuf)
{
break;
}
// 打开输入文件
hSrcFile = CreateFile(lpSrcFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hSrcFile)
{
break;
}
// 打开输出文件
hDestFile = CreateFile(lpDestFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hDestFile)
{
break;
}
DWORD dwRead = 0;
DWORD dwWritten = 0;
int nResult = 0;
while (TRUE)
{
// 读取输入数据
if (!ReadFile(hSrcFile, lpInputBuf, dwInputBufSize, &dwRead, NULL))
{
nResult = Z_ERRNO;
break;
}
// 文件读取完毕退出循环
if (0 == dwRead)
{
break;
}
// 压缩数据块
DWORD dwOutCompressSize = dwOutputBufSize;
nResult = compress2((Bytef*)lpOutputBuf, &dwOutCompressSize, (Bytef*)lpInputBuf, dwRead, Z_DEFAULT_COMPRESSION);
if (Z_OK != nResult)
{
break;
}
// 填充块信息
ZDF_HEADER zdf = { 0 };
zdf.dwFlag = ZDF_HEADER_FLAG;
zdf.dwRawDataSize = dwRead;
zdf.dwDataSize = dwOutCompressSize;
zdf.dwCheckSum = zdf.dwFlag + zdf.dwRawDataSize + zdf.dwDataSize;
// 写入块信息
if (FALSE == WriteFile(hDestFile, &zdf, sizeof(zdf), &dwWritten, NULL))
{
nResult = Z_ERRNO;
break;
}
// 写入压缩数据
if (FALSE == WriteFile(hDestFile, lpOutputBuf, dwOutCompressSize, &dwWritten, NULL))
{
nResult = Z_ERRNO;
break;
}
}
if (0 != nResult)
{
break;
}
fResult = TRUE;
} while (FALSE);
if (NULL != lpOutputBuf)
{
HeapFree(GetProcessHeap(), 0, lpOutputBuf);
}
if (NULL != lpInputBuf)
{
HeapFree(GetProcessHeap(), 0, lpInputBuf);
}
if (INVALID_HANDLE_VALUE != hSrcFile)
{
CloseHandle(hSrcFile);
}
if (INVALID_HANDLE_VALUE != hDestFile)
{
CloseHandle(hDestFile);
}
// 失败则删除输出文件
if (FALSE == fResult)
{
DeleteFile(lpDestFileName);
}
return fResult;
}
BOOL UncompressFile(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
)
{
HANDLE hDestFile = INVALID_HANDLE_VALUE;
HANDLE hSrcFile = INVALID_HANDLE_VALUE;
LPVOID lpOutputBuf = NULL;
LPVOID lpInputBuf = NULL;
BOOL fResult = FALSE;
do
{
DWORD dwInputBufSize = ZDF_BLOCK_SIZE; // 读取块大小
DWORD dwOutputBufSize = dwInputBufSize * 2; // 输出块设为输入块2倍
// 分配输入缓冲
lpInputBuf = HeapAlloc(GetProcessHeap(), 0, dwInputBufSize);
if (NULL == lpInputBuf)
{
break;
}
// 分配输出缓冲
lpOutputBuf = HeapAlloc(GetProcessHeap(), 0, dwOutputBufSize);
if (NULL == lpOutputBuf)
{
break;
}
// 打开输入文件
hSrcFile = CreateFile(lpSrcFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hSrcFile)
{
break;
}
// 打开输出文件
hDestFile = CreateFile(lpDestFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hDestFile)
{
break;
}
DWORD dwRead = 0;
DWORD dwWritten = 0;
int nResult = 0;
while (TRUE)
{
ZDF_HEADER zdf = { 0 };
// 读取压缩块大小
if (!ReadFile(hSrcFile, &zdf, sizeof(zdf), &dwRead, NULL))
{
break;
}
// 文件读取完毕退出循环
if (0 == dwRead)
{
break;
}
//检查块信息
if (zdf.dwCheckSum != (zdf.dwFlag + zdf.dwRawDataSize + zdf.dwDataSize))
{
nResult = Z_ERRNO;
break;
}
// 扩充输入缓冲(默认缓冲不够时)
if (zdf.dwDataSize > dwInputBufSize)
{
// 释放旧缓冲
if (FALSE == HeapFree(GetProcessHeap(), 0, lpInputBuf))
{
nResult = Z_ERRNO;
break;
}
// 分配新缓冲
dwInputBufSize = zdf.dwDataSize;
lpInputBuf = HeapAlloc(GetProcessHeap(), 0, dwInputBufSize);
if (NULL == lpInputBuf)
{
nResult = Z_ERRNO;
break;
}
}
// 扩充输出缓冲(默认缓冲不够时)
if (zdf.dwRawDataSize > dwOutputBufSize)
{
// 释放旧缓冲
if (FALSE == HeapFree(GetProcessHeap(), 0, lpOutputBuf))
{
nResult = Z_ERRNO;
break;
}
// 分配新缓冲
dwOutputBufSize = zdf.dwRawDataSize;
lpOutputBuf = HeapAlloc(GetProcessHeap(), 0, dwOutputBufSize);
if (NULL == lpOutputBuf)
{
nResult = Z_ERRNO;
break;
}
}
// 读取压缩块
if (!ReadFile(hSrcFile, lpInputBuf, zdf.dwDataSize, &dwRead, NULL))
{
break;
}
// 解压数据块
DWORD dwOutCompressSize = dwOutputBufSize;
nResult = uncompress((Bytef*)lpOutputBuf, &dwOutCompressSize, (Bytef*)lpInputBuf, dwRead);
if (Z_OK != nResult)
{
break;
}
// 输出到文件
if (!WriteFile(hDestFile, lpOutputBuf, dwOutCompressSize, &dwWritten, NULL))
{
nResult = Z_ERRNO;
break;
}
}
if (0 != nResult)
{
break;
}
fResult = TRUE;
} while (FALSE);
if (NULL != lpInputBuf)
{
HeapFree(GetProcessHeap(), 0, lpInputBuf);
}
if (NULL != lpOutputBuf)
{
HeapFree(GetProcessHeap(), 0, lpOutputBuf);
}
if (INVALID_HANDLE_VALUE != hSrcFile)
{
CloseHandle(hSrcFile);
}
if (INVALID_HANDLE_VALUE != hDestFile)
{
CloseHandle(hDestFile);
}
// 失败则删除输出文件
if (FALSE == fResult)
{
DeleteFile(lpDestFileName);
}
return fResult;
}
BOOL compress_file(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
)
{
FILE* hSrcFile = NULL;
FILE* hDestFile = NULL;
void* lpOutputBuf = NULL;
void* lpInputBuf = NULL;
BOOL fResult = FALSE;
do
{
size_t dwInputBufSize = ZDF_BLOCK_SIZE; // 读取块大小
size_t nOutputBufSize = dwInputBufSize * 2; // 输出块设为输入块2倍
errno_t err = 0;
// 分配缓冲
lpInputBuf = malloc(dwInputBufSize);
if (NULL == lpInputBuf)
{
break;
}
// 分配缓冲
lpOutputBuf = malloc(nOutputBufSize);
if (NULL == lpOutputBuf)
{
break;
}
err = _tfopen_s(&hSrcFile, lpSrcFileName, _T("rb"));
if (0 != err)
{
break;
}
err = _tfopen_s(&hDestFile, lpDestFileName, _T("wb"));
if (0 != err)
{
break;
}
size_t nReadSize = 0;
size_t nWritten = 0;
int nResult = 0;
while (TRUE)
{
size_t nReadReady = dwInputBufSize;
// 读取输入数据
nReadSize = fread_s(lpInputBuf, dwInputBufSize, 1, nReadReady, hSrcFile);
// 文件读取完毕退出循环
if (0 == nReadSize)
{
break;
}
if (0 != ferror(hSrcFile))
{
break;
}
// 压缩数据块
size_t nOutCompressSize = nOutputBufSize;
nResult = compress2((Bytef*)lpOutputBuf, &nOutCompressSize, (Bytef*)lpInputBuf, nReadSize, Z_DEFAULT_COMPRESSION);
if (Z_OK != nResult)
{
break;
}
// 填充块信息
ZDF_HEADER zdf = { 0 };
zdf.dwFlag = ZDF_HEADER_FLAG;
zdf.dwRawDataSize = nReadSize;
zdf.dwDataSize = nOutCompressSize;
zdf.dwCheckSum = zdf.dwFlag + zdf.dwRawDataSize + zdf.dwDataSize;
if (0 == fwrite(&zdf, sizeof(zdf), 1, hDestFile))
{
break;
}
if (nOutCompressSize != fwrite(lpOutputBuf, 1, nOutCompressSize, hDestFile))
{
break;
}
}
if (0 != nResult)
{
break;
}
fResult = TRUE;
} while (FALSE);
if (NULL != lpOutputBuf)
{
free(lpOutputBuf);
}
if (NULL != lpInputBuf)
{
free(lpInputBuf);
}
if (NULL != hSrcFile)
{
fclose(hSrcFile);
}
if (NULL != hDestFile)
{
fclose(hDestFile);
}
// 失败则删除输出文件
if (FALSE == fResult)
{
_tremove(lpDestFileName);
}
return fResult;
}
BOOL uncompress_file(
LPCTSTR lpSrcFileName, // 输入文件
LPCTSTR lpDestFileName // 输出文件
)
{
FILE* hSrcFile = NULL;
FILE* hDestFile = NULL;
void* lpOutputBuf = NULL;
void* lpInputBuf = NULL;
BOOL fResult = FALSE;
do
{
size_t nInputBufSize = ZDF_BLOCK_SIZE; // 读取块大小
size_t nOutputBufSize = nInputBufSize * 2; // 输出块设为输入块2倍
errno_t err = 0;
// 分配缓冲
lpInputBuf = malloc(nInputBufSize);
if (NULL == lpInputBuf)
{
break;
}
// 分配缓冲
lpOutputBuf = malloc(nOutputBufSize);
if (NULL == lpOutputBuf)
{
break;
}
err = _tfopen_s(&hSrcFile, lpSrcFileName, _T("rb"));
if (0 != err)
{
break;
}
err = _tfopen_s(&hDestFile, lpDestFileName, _T("wb"));
if (0 != err)
{
break;
}
size_t nWritten = 0;
int nResult = 0;
while (TRUE)
{
ZDF_HEADER zdf = { 0 };
size_t nReadSize = 0;
// 读取压缩块大小
nReadSize = fread_s(&zdf, sizeof(zdf), 1, sizeof(zdf), hSrcFile);
if (0 == nReadSize)
{
break;
}
if (0 != ferror(hSrcFile))
{
break;
}
//检查块信息
if (zdf.dwCheckSum != (zdf.dwFlag + zdf.dwRawDataSize + zdf.dwDataSize))
{
nResult = Z_ERRNO;
break;
}
// 扩充输入缓冲(默认缓冲不够时)
if (zdf.dwDataSize > nInputBufSize)
{
// 释放旧缓冲
free(lpInputBuf);
// 分配新缓冲
nInputBufSize = zdf.dwDataSize;
lpInputBuf = malloc(nInputBufSize);
if (NULL == lpInputBuf)
{
nResult = Z_ERRNO;
break;
}
}
// 扩充输出缓冲(默认缓冲不够时)
if (zdf.dwRawDataSize > nOutputBufSize)
{
// 释放旧缓冲
free(lpOutputBuf);
// 分配新缓冲
nOutputBufSize = zdf.dwRawDataSize;
lpOutputBuf = malloc(nOutputBufSize);
if (NULL == lpOutputBuf)
{
nResult = Z_ERRNO;
break;
}
}
// 读取压缩块
nReadSize = fread_s(lpInputBuf, nInputBufSize, 1, zdf.dwDataSize, hSrcFile);
if (0 == nReadSize)
{
break;
}
if (0 != ferror(hSrcFile))
{
break;
}
// 解压数据块
DWORD nOutCompressSize = nOutputBufSize;
nResult = uncompress((Bytef*)lpOutputBuf, &nOutCompressSize, (Bytef*)lpInputBuf, zdf.dwDataSize);
if (Z_OK != nResult)
{
break;
}
// 输出到文件
if (!fwrite(lpOutputBuf, nOutCompressSize, 1, hDestFile))
{
nResult = Z_ERRNO;
break;
}
}
if (0 != nResult)
{
break;
}
fResult = TRUE;
} while (FALSE);
if (NULL != lpInputBuf)
{
free(lpInputBuf);
}
if (NULL != lpOutputBuf)
{
free(lpOutputBuf);
}
if (NULL != hSrcFile)
{
fclose(hSrcFile);
}
if (NULL != hDestFile)
{
fclose(hDestFile);
}
// 失败则删除输出文件
if (FALSE == fResult)
{
_tremove(lpDestFileName);
}
return fResult;
}
main.c
#include "zlib_utils.h"
int main()
{
compress_file(_T("zlib_test.pdb"), _T("zlib_test.zdf"));
uncompress_file(_T("zlib_test.zdf"), _T("zlib_test_out.pdb"));
return 0;
}