zlib压缩解压文件

54 篇文章 0 订阅
32 篇文章 0 订阅

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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值