• 数据压缩API


    前言:

      为了实现windows上的数据压缩和解压缩,最方便的方法就是直接调用WIN32 API函数,windows系统的ntdll.dll专门提供了RtlCompressBuffer函数和RtlDecompressBuffer函数来负责数据压缩和解压缩操作,这两个函数并未公开,需要通过ntdll.dll来动态调用。

    实现过程:

      一、数据压缩:

        (1).调用LoadLibrary函数加载ntdll.dll,获取ntdll.dll加载模块的句柄

        (2).调用GetProcAddress函数获取RtlGetCompressionWorkSpaceSize函数与RtlCompressBuffer函数的地址

        (3).调用RtlGetCompressionWorkSpaceSize函数来获取RtlCompressBuffer函数的工作空间缓冲区的大小(压缩格式和引擎类型设置为COMPRESSION_FORMAT_LZNT1和COMPRESSION_ENGINE_STANDARD)

        (4).根据工作空间缓冲区的大小申请内存给压缩数据使用

        (5).调用RtlCompressBuffer函数来压缩数据。数据压缩缓冲区的大小为4096字节

        注意:需要将实际的压缩数据大小和数据压缩缓冲区的大小进行比较,如果数据压缩缓冲区太小,则需要释放原来的缓冲区,按照实际压缩数据的大小重新申请一个新的数据压缩缓冲区,并且重新压缩数据

      二、数据解压缩

        (1).调用LoadLibrary函数加载ntdll.dll,并获取ntdll.dll加载模块的句柄

        (2).调用GetProcAddress函数来获取RtlDecompressBuffer函数

        (3).申请一块内存,大小为4096字节,存放解压缩后的数据

        (4).调用RtlDecompressBuffer函数来解压缩数据(压缩格式和引擎类型必须设置为COMPRESSION_FORMAT_LZNT1)

        注意:需要将实际的解压数据大小和数据解压缓冲区的大小进行比较,如果数据解压缓冲区太小,则需要释放原来的缓冲区,按照实际解压数据的大小重新申请一个新的数据解压缓冲区,并且重新解压缩数据    

    实现代码:

        //************************************
        // 函数名:CCondenseDlg::DataCompress
        // 返回类型:BOOL
        // 功能:    数据压缩
        // 参数1:BYTE* pUncompressData 未压缩的数据
        // 参数2:DWORD dwUncompressDataLength    未压缩的数据的数据大小
        // 参数3:BYTE** ppCompressData    压缩后的数据
        // 参数4:DWORD* pdwCompressDataLength    压缩后的数据大小
        //************************************
    BOOL CCondenseDlg::DataCompress(BYTE* pUncompressData, DWORD dwUncompressDataLength, BYTE** ppCompressData, DWORD* pdwCompressDataLength)
    {
        BOOL bRet = FALSE;
        NTSTATUS status = 0;
        HMODULE hModule = NULL;
    
        //定义函数指针变量
        typedef_RtlGetCompressionWorkSpaceSize RtlGetCompressionWorkSpaceSize = NULL;
        typedef_RtlCompressBuffer RtlCompressBuffer = NULL;
    
        DWORD dwWorkSpaceSize = 0;
        DWORD dwFragmentWorkSpaceSize = 0;
        BYTE* pWorkSpace = NULL;
        BYTE* pCompressData = NULL;
        DWORD dwCompressDataLength = 4096;
        DWORD dwFinalCompressSize = 0;
    
        //加载ntdll.dll
        hModule = LoadLibrary(_T("ntdll.dll"));
        if (hModule == NULL)
        {
            m_Tip += _T("LoadLibrary Error
    ");
            return bRet;
        }
    
        //获取函数地址
        RtlGetCompressionWorkSpaceSize = (typedef_RtlGetCompressionWorkSpaceSize)::GetProcAddress(hModule, "RtlGetCompressionWorkSpaceSize");
        if (NULL == RtlGetCompressionWorkSpaceSize)
        {
            m_Tip += _T("GetProcAddress Error
    ");
            FreeLibrary(hModule);
            return bRet;
        }
    
        RtlCompressBuffer = (typedef_RtlCompressBuffer)::GetProcAddress(hModule, "RtlCompressBuffer");
        if (NULL == RtlCompressBuffer)
        {
            m_Tip += _T("GetProcAddress Error
    ");
            FreeLibrary(hModule);
            return bRet;
        }
    
        //获取WorkSpace大小
        status = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD,
            &dwWorkSpaceSize, &dwFragmentWorkSpaceSize);
        if (0 != status)
        {
            m_Tip += _T("RtlGetCompressionWorkSpaceSize Error
    ");
            FreeLibrary(hModule);
            return bRet;
        }
    
        //申请动态内存
        pWorkSpace = new BYTE[dwWorkSpaceSize]{ 0 };
        if (pWorkSpace == NULL)
        {
            m_Tip += _T("new Error
    ");
            FreeLibrary(hModule);
            return bRet;
        }
    
        while (TRUE)
        {
            //申请动态内存存储压缩后的数据
            pCompressData = new BYTE[dwCompressDataLength];
            if (pCompressData == NULL)
            {
                m_Tip += _T("new Error
    ");
                delete[] pWorkSpace;
                FreeLibrary(hModule);
                return bRet;
            }
    
            //开始压缩数据 
            RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, pUncompressData, dwUncompressDataLength,
                (PUCHAR)pCompressData, dwCompressDataLength, 4096, &dwFinalCompressSize, (PVOID)pWorkSpace);
    
            //如果压缩数据的缓冲区小于最终的压缩大小 说明压缩失败 需要重新压缩
            if (dwCompressDataLength < dwFinalCompressSize)
            {
                //释放内存
                if (pCompressData)
                {
                    delete[] pCompressData;
                }
                dwCompressDataLength = dwFinalCompressSize;
            }
            else
            {
                //否则说明压缩成功 退出循环
                break;
            }
        }
    
        //返回压缩后的数据和长度
        *ppCompressData = pCompressData;
        *pdwCompressDataLength = dwFinalCompressSize;
        bRet = TRUE;
    
        //释放资源
        if (pWorkSpace)
        {
            delete[] pWorkSpace;
        }
        if (hModule)
        {
            FreeLibrary(hModule);
        }
        return bRet;
    }
        //************************************
        // 函数名:CCondenseDlg::UncompressData
        // 返回类型:BOOL
        // 功能:    数据解压缩
        // 参数1:BYTE *pCompressData 压缩的数据
        // 参数2:DWORD dwCompressDataLength 压缩的数据大小
        // 参数3:BYTE **ppUncompressData 解压缩的数据
        // 参数4:DWORD *pdwUncompressDataLength 解压缩的数据大小
        //*BOOL CCondenseDlg::UncompressData(BYTE *pCompressData, DWORD dwCompressDataLength, BYTE **ppUncompressData, DWORD *pdwUncompressDataLength)
    {
        BOOL bRet = FALSE;
        HMODULE hModule = NULL;
        typedef_RtlDecompressBuffer RtlDecompressBuffer = NULL;
        BYTE* pUncompressData = NULL;
        DWORD dwUncompressDataLength = 4096;
        DWORD dwFinalUncompressSize = 0;
    
        // 加载 ntdll.dll 
        hModule = ::LoadLibrary(_T("ntdll.dll"));
        if (NULL == hModule)
        {
            m_Tip += _T("LoadLibrary Error
    ");
            return bRet;
        }
    
        // 获取 RtlDecompressBuffer 函数地址
        RtlDecompressBuffer = (typedef_RtlDecompressBuffer)::GetProcAddress(hModule, "RtlDecompressBuffer");
        if (NULL == RtlDecompressBuffer)
        {
            m_Tip += _T("GetProcAddress Error
    ");
            FreeLibrary(hModule);
            return bRet;
        }
    
        while (TRUE)
        {
            // 申请动态内存
            pUncompressData = new BYTE[dwUncompressDataLength];
            if (NULL == pUncompressData)
            {
                m_Tip += _T("new Error
    ");
                FreeLibrary(hModule);
                return bRet;
            }
            ::RtlZeroMemory(pUncompressData, dwUncompressDataLength);
    
            // 调用RtlCompressBuffer压缩数据
            RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, pUncompressData, dwUncompressDataLength, pCompressData, dwCompressDataLength, &dwFinalUncompressSize);
            if (dwUncompressDataLength < dwFinalUncompressSize)
            {
                // 释放内存
                if (pUncompressData)
                {
                    delete[] pUncompressData;
                    pUncompressData = NULL;
                }
                dwUncompressDataLength = dwFinalUncompressSize;
            }
            else
            {
                break;
            }
        }
    
        //返回解压后的数据和长度
        *ppUncompressData = pUncompressData;
        *pdwUncompressDataLength = dwFinalUncompressSize;
        bRet = TRUE;
    
        //释放资源
        if (hModule)
        {
            ::FreeLibrary(hModule);
        }
    
        return bRet;
    }
    ***********************************
  • 相关阅读:
    html表单的创建
    mysql数据库连接标准操作
    关于Apache+MySQL+PHP下载及配置注意事项
    两个范例
    Stack类
    Collections类集
    key可以重复的map集合:IdentityHashMap
    foreach对集合的输出作用
    ListIterator接口
    【官方方法】xcode7免证书真机调试
  • 原文地址:https://www.cnblogs.com/ndyxb/p/12910398.html
Copyright © 2020-2023  润新知