QT4.8.6调用zlib库实现数据流的压缩与解压缩

转载sunnysab :https://blog.csdn.net/sunnysab/article/details/46672949

ZLIB库

ZLIB版本zlib 1.2.11  地址:http://www.zlib.net

  • 使用

接口说明

/**

 压缩

参数一Bytef *dest:压缩后的字节

参数二uLongf *destLen:压缩后的字节长度 

参数三const Bytef *source:待压缩的字节

参数四uLong sourceLen :待压缩的字节长度

**/

int compress (Bytef *dest,   uLongf *destLen,const Bytef *source, uLong sourceLen);

/*
    根据待压缩长度返回压缩以后的数据长度
*/ 

ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));

/**

 解压缩

参数一Bytef *dest:解压缩后的字节

参数二uLongf *destLen:解压缩后的字节长度,返回值是实际解压缩以后的长度 

参数三const Bytef *source:待解压缩的字节数据

参数四uLong sourceLen :待解压缩的字节长度

**/

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,const Bytef *source, uLong sourceLen)); 

QT封装的函数 

/**

 压缩

参数一OutEncodeData:压缩后的数据,返回值QByteArray

参数二InRawData:待压缩的数据

参数三nErrorCode:返回故障码

**/

    long ZlibCompress(QByteArray &OutEncodeData,QByteArray InRawData, int *nErrorCode);

/**

 解压缩

参数一OutEncodeData:解压缩后的数据,返回值QByteArray

参数二InRawData:待解压缩的数据

参数三nErrorCode:返回值故障码

**/

    long ZlibUncompress(QByteArray &OutDecodeData,QByteArray InEncodeData,int *nErrorCode); 

/**

 根据长度获取长度

**/

    int  ZlibGetDecodeLength(uLong  InRawLength);

/**

 根据QByteArray获取压缩解压缩长度

**/

    int  ZlibGetDecodeLength(QByteArray  InRawData);

/*
 * 函  数: ZlibGetDecodeLength
 * 功  能: 通过要压缩的数据大小,得到压缩后数据的最大大小
 *        以此设置缓冲区
 * 参  数: uLong  InRawLength  压缩前数据大小
 */

int  MainWindow::ZlibGetDecodeLength(uLong  InRawLength)
{
    return  compressBound(InRawLength);
}

/*
 * 函  数: ZlibGetDecodeLength
 * 功  能: 通过要压缩的数据大小,得到压缩后数据的最大大小
 *        以此设置缓冲区
 * 参  数: QByteArray  InRawData  压缩前数据
 *
 */
int  MainWindow::ZlibGetDecodeLength(QByteArray  InRawData)
{
    // 注:
    // ((QByteArray)"Hello").size() == 5
    // 因为当字符串为 QByteArray , '\0' 被忽略
    return  compressBound(InRawData.length());
}

/*
 * 函  数: ZlibCompress
 * 功  能: 执行压缩操作
 * 参  数: QByteArray  &OutEncodeData  压缩后数据
 *        QByteArray  InRawData       要压缩的数据
          int       * nErrorCode      错误代码
 * 说  明: 当 nErrorCode 不为 NULL 时, 若 compress 出错后, 其数据改为
 *          compress 返回的错误代码. 在 zlib.h 中可以找到.
 *        例如: -5  缓冲区长度不够
 * 返回值: 类型 long
 *        返回压缩后的长度, -1 表示压缩失败, 请检查 *nErrorCode .
 */

long  MainWindow::ZlibCompress(QByteArray  &OutEncodeData, QByteArray  InRawData,
                  int  * nErrorCode = NULL)
{
    Bytef  *EncodeData = NULL;  // 压缩后的数据暂存于此
    int     nFuncRet = Z_ERRNO; // 随便找个错误代码先填着
    long    nOutLength = 0;
    // 申请最大缓冲区
    nOutLength = ZlibGetDecodeLength(InRawData.length());
    EncodeData = new Bytef[nOutLength];
    if (NULL != EncodeData)
    {
        // 调用 compress 函数前, nOutLength 要置为缓冲区大小
        nFuncRet = compress(EncodeData, (uLongf *)&nOutLength, (Bytef *)InRawData.data(),
                            InRawData.length());

        if (Z_OK == nFuncRet)
        {
            // 自己设置好长度为好, 省的 '\0' 被截断了
            OutEncodeData.append((const char *)EncodeData, nOutLength);
        }
        else
        {
            nOutLength = -1;
        }
    }
    delete  EncodeData;

    // 输出错误代码
    if (NULL != nErrorCode)
    {
        *nErrorCode = nFuncRet;
    }
    return  nOutLength;
}

解压缩函数简介 

/*
 * 函  数: ZlibUnCompress
 * 功  能: 执行解压操作
 * 参  数: QByteArray  &OutDecodeData  解压后数据
 *        QByteArray  InEncodeData    要解压的数据
          int       * nErrorCode      错误代码
 * 说  明: 当 nErrorCode 不为 NULL 时, 若 uncompress 出错后, 其数据改为
 *          uncompress 返回的错误代码. 在 zlib.h 中可以找到.
 *        例如: -5  缓冲区长度不够
 * 返回值: 类型 long
 *        返回解压后的长度, -1 表示解压失败, 请检查 *nErrorCode .
 */

long  MainWindow::ZlibUncompress(QByteArray  &OutDecodeData, QByteArray InEncodeData,
                     int   * nErrorCode = NULL)
{
    Bytef  *DecodeData = NULL; // 解压后的数据缓冲区
    Bytef  *EncodeData_Buffer = NULL;  // 要解压的数据缓冲区, 后面用memcpy放到这
    int     nFuncRet = Z_ERRNO;
    uLongf  nOutLength = 0;

    // 说明:
    // 如果压缩后大小比之前小, 缓冲区大小应该设置多少?
    // 暂且把 ZlibGetDecodeLength 拿来用用, 确保缓冲区够了.
    //nOutLength = ZlibGetDecodeLength(InEncodeData.length());
    nOutLength = InEncodeData.length()*4;   //
    qDebug()<<"InEncodeData.length"<<InEncodeData.length();
    qDebug()<<"nOutLength"<<nOutLength;

    // 为缓冲区申请内存
    DecodeData        =  new Bytef[nOutLength];
    EncodeData_Buffer =  new Bytef[nOutLength];

    if (NULL != DecodeData && NULL != EncodeData_Buffer)
    {
        // 由于 QByteArray 在 data() 函数中会因为'\0'截断
        // (先鄙视一下,那还叫什么字节操作)
        // 文档又说,constData() 效率高
        // 所以用 constData() 获取地址然后 memcpy 自己复制
        memcpy(EncodeData_Buffer, InEncodeData.constData(), InEncodeData.size());

        nFuncRet = uncompress(DecodeData, &nOutLength, (Bytef *)EncodeData_Buffer,
                              InEncodeData.length());
        qDebug()<<"nFuncRet"<<nFuncRet;
        if (Z_OK == nFuncRet)
        {
            OutDecodeData.append((const char *)DecodeData, nOutLength);
        }
        else
        {
            nOutLength = -1;
        }
    }
    else
    {
        nOutLength = -1;
    }

    // 清理 new 产生的内存
    if (NULL != DecodeData)
    {
        delete  DecodeData;
    }

    if (NULL != EncodeData_Buffer)
    {
        delete  EncodeData_Buffer;
    }

    // 输出错误代码
    if (NULL != nErrorCode)
    {
        *nErrorCode = nFuncRet;
    }
    return  nOutLength;

}

函数调用测试 


void MainWindow::on_pushButton_clicked()
{
    QString mFileName = "request.xml";
    QString mSeqFileName = "sequence.xml";
    quint64 totalBytes;
    QFile file(mFileName);
    QByteArray SendByte;
    QByteArray OutByte;
    int *errorCode = NULL;
    if(!file.open(QFile::ReadOnly))
    {
        qDebug() << QString("Send file error! Cannot read XmlFile %1(%2).").arg(mFileName).arg(file.errorString());
        return;
    }

    QDataStream out(&SendByte, QIODevice::WriteOnly);
    totalBytes = file.size();
    out.device()->seek(0);
    out<<file.readAll();
    file.close();
    SendByte.remove(0,4);
    qDebug()<<"totalBytes = "<<totalBytes;
    qDebug()<<"SendByte = "<<SendByte.toHex();

    long outlength = ZlibCompress(OutByte,SendByte,errorCode);
    if(outlength != (-1))
    {
        qDebug()<<"OutByte = "<<OutByte.toHex();
        qDebug()<<"outlength = "<<outlength;

    }

 const char m_code[] = {0x78,0x9C,0x4D,0x4F,0xD1,0x0A,0x83,0x30,0x0C,0x7C,0x1F,0xEC,0x1F,0xA4,0xEF,0x5B,0x5B,0x61,0x30,0x21,0xD6,0xB7,0x7D,0xC1,0xF6,0x2C,0x9D,0x0D,0x52,0xD0,0x46,0x6B,0x75,0xF3,0xEF,0xD7,0x09,0x4A,0xF3,0x94,0xCB,0x5D,0xEE,0x12,0xA8,0xBE,0x7D,0x97,0x2D,0xE8,0x27,0x4B,0xAE,0x64,0xF2,0x2A,0x58,0x86,0xAE,0x21,0x63,0x5D,0x5B,0xB2,0xD7,0xF3,0x71,0xB9,0xB3,0x4A,0x81,0x27,0x0A,0x0A,0x1A,0xEA,0x7B,0x72,0x0A,0xDE,0xB3,0xED,0xFE,0x82,0xDA,0x1A,0x25,0x44,0x7E,0x13,0x42,0xC8,0x58,0xC0,0x53,0x02,0x5A,0x1D,0xF0,0xA3,0xD7,0x54,0x04,0x3C,0x19,0x42,0x58,0x07,0x54,0x13,0x8E,0x73,0x0C,0x44,0xE0,0x1B,0x04,0xBE,0x87,0x58,0x53,0x2F,0xBA,0xB3,0x26,0x2E,0x64,0x34,0xA0,0xD7,0x61,0xBB,0x70,0xD7,0x33,0x05,0x7B,0x1B,0xED,0x8F,0x92,0x45,0x21,0x73,0xE0,0x07,0x05,0x3C,0xF1,0x89,0x68,0x7B,0xE4,0x7C,0xFA,0x01,0xF3,0xF1,0x52,0x91};
    QByteArray mInCode;
    QByteArray mOutCode;
    mInCode.append(m_code,sizeof(m_code));
    qDebug()<<"mInCode = "<<mInCode.toHex();
    long decodelenth = ZlibUncompress(mOutCode,mInCode,errorCode);
    qDebug()<<"decodelenth = "<<decodelenth;
    if(decodelenth != (-1))
    {
        qDebug()<<"mOutCode = "<<mOutCode.toHex();
        qDebug()<<"decodelenth = "<<decodelenth;
    }

    QFile m_SecFile(mSeqFileName);
    if(!m_SecFile.open(QFile::WriteOnly)) return;
    m_SecFile.resize(0);//清空原有图片内容
    m_SecFile.write(mOutCode.data(),mOutCode.size());
    m_SecFile.close();

    changeXML(mSeqFileName);

    //QString m_strType = "";
    //if(!parse(mOutCode,m_strType)){
      //  qDebug() <<"parse error!";
    //}
    //qDebug() <<"m_strType:"<<m_strType;
}

猜你喜欢

转载自blog.csdn.net/sampson_sxz/article/details/81390489