QT + LZMA SDK文件压缩及解压

环境

Qt 5.4.2
LZMA SDK

功能

使用LZMA SDK 实现文件压缩及解压

编写LZMA库

1.下载LZMA SDK,并编写C语言库
在这里插入图片描述
2.修改Pro文件
在这里插入图片描述

3.将下载的LZMA SDK C源码文件添加到项目
在这里插入图片描述
3.新建LzmaDll.h,LzmaDll.cpp
LzmaDll.h源码:

extern int LzmaCompressFun(const char *srcFilePath, const char * tarFilePath);    //压缩
extern int LzmaUncompressFun(const char *srcFilePath, const char * tarFilePath);  //解压

//
#define IN_BUF_SIZE (1 << 16)
#define OUT_BUF_SIZE (1 << 16)

static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs);
static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream);
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,UInt64 unpackSize);

LzmaDll.cpp源码:

static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs)
{
  CLzmaEncHandle enc;
  SRes res;
  CLzmaEncProps props;

  UNUSED_VAR(rs);

  enc = LzmaEnc_Create(&g_Alloc);
  if (enc == 0)
    return SZ_ERROR_MEM;

  LzmaEncProps_Init(&props);

  props.level = 3;

  LzmaEncProps_Normalize(&props);
  res = LzmaEnc_SetProps(enc, &props);

  if (res == SZ_OK)
  {
    Byte header[LZMA_PROPS_SIZE + 8];
    size_t headerSize = LZMA_PROPS_SIZE;
    int i;

    res = LzmaEnc_WriteProperties(enc, header, &headerSize);
    for (i = 0; i < 8; i++)
      header[headerSize++] = (Byte)(fileSize >> (8 * i));
    if (outStream->Write(outStream, header, headerSize) != headerSize)
      res = SZ_ERROR_WRITE;
    else{
        if (res == SZ_OK)
        res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc);
    }
  }
  LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
  return res;
}
static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream)
{
  UInt64 unpackSize;
  int i;
  SRes res = 0;

  CLzmaDec state;

  /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
  unsigned char header[LZMA_PROPS_SIZE + 8];

  /* Read and parse header */

  RINOK(SeqInStream_Read(inStream, header, sizeof(header)));

  unpackSize = 0;
  for (i = 0; i < 8; i++)
    unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);

  LzmaDec_Construct(&state);
  RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
  res = Decode2(&state, outStream, inStream, unpackSize);
  LzmaDec_Free(&state, &g_Alloc);
  return res;
}
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,UInt64 unpackSize)
{
  int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
  Byte inBuf[IN_BUF_SIZE];
  Byte outBuf[OUT_BUF_SIZE];
  size_t inPos = 0, inSize = 0, outPos = 0;
  LzmaDec_Init(state);
  for (;;)
  {
    if (inPos == inSize)
    {
      inSize = IN_BUF_SIZE;
      RINOK(inStream->Read(inStream, inBuf, &inSize));
      inPos = 0;
    }
    {
      SRes res;
      SizeT inProcessed = inSize - inPos;
      SizeT outProcessed = OUT_BUF_SIZE - outPos;
      ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
      ELzmaStatus status;
      if (thereIsSize && outProcessed > unpackSize)
      {
        outProcessed = (SizeT)unpackSize;
        finishMode = LZMA_FINISH_END;
      }

      res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
        inBuf + inPos, &inProcessed, finishMode, &status);
      inPos += inProcessed;
      outPos += outProcessed;
      unpackSize -= outProcessed;

      if (outStream)
        if (outStream->Write(outStream, outBuf, outPos) != outPos)
          return SZ_ERROR_WRITE;

      outPos = 0;

      if (res != SZ_OK || (thereIsSize && unpackSize == 0))
        return res;

      if (inProcessed == 0 && outProcessed == 0)
      {
        if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
          return SZ_ERROR_DATA;
        return res;
      }
    }
  }
}

int LzmaCompressFun(const char *srcFilePath, const char * tarFilePath)
{
    int nRtn = 0;
    char rs[1000] = { 0 };
    
    CFileSeqInStream inStream;
    CFileOutStream outStream;
    LzFindPrepare();

    FileSeqInStream_CreateVTable(&inStream);
    File_Construct(&inStream.file);
    inStream.wres = 0;

    FileOutStream_CreateVTable(&outStream);
    File_Construct(&outStream.file);
    outStream.wres = 0;
    WRes wres = InFile_Open(&inStream.file, srcFilePath);

    if (wres != 0) {
        return -1;  //PrintError_WRes(rs, "Cannot open input file", wres);
    }

    wres = OutFile_Open(&outStream.file, tarFilePath);

    UInt64 fileSize;
    wres = File_GetLength(&inStream.file, &fileSize);

    if (wres != 0) {
        return -3; //PrintError_WRes(rs, "Cannot get file length", wres);
    }
    nRtn = Encode(&outStream.vt, &inStream.vt, fileSize, rs);
    File_Close(&outStream.file);
    File_Close(&inStream.file);
    return nRtn;
}
int LzmaUncompressFun(const char *srcFilePath, const char *tarFilePath)
{
    int nRtn = 0;
    CFileSeqInStream inStream;
    CFileOutStream outStream;
    LzFindPrepare();
    FileSeqInStream_CreateVTable(&inStream);
    File_Construct(&inStream.file);
    inStream.wres = 0;
    FileOutStream_CreateVTable(&outStream);
    File_Construct(&outStream.file);
    outStream.wres = 0;
    WRes wres = InFile_Open(&inStream.file, srcFilePath);
    if (wres != 0) {
        return -1;  //PrintError_WRes(rs, "Cannot open input file", wres);
    }
    wres = OutFile_Open(&outStream.file, tarFilePath);
    UInt64 fileSize;
    wres = File_GetLength(&inStream.file, &fileSize);
    if (wres != 0) {
        return -3; //PrintError_WRes(rs, "Cannot get file length", wres)
    }
    nRtn = Decode(&outStream.vt, &inStream.vt);
    File_Close(&outStream.file);
    File_Close(&inStream.file);
    return nRtn;
}

QT 调用LZMA

1.新建QT 工程
在这里插入图片描述
2.修改Pro文件

INCLUDEPATH += “G:/LzmaDemo/LzmaDLL/”
LIBS += -LG:/LzmaDemo/LzmaDLL/Build-Release/release/ -lLzmaDLL

3.mainWindow.h源码

namespace Ui {class MainWindow;}

#ifdef  __cplusplus
extern "C" {
#endif
#include "LzmaDLL.h"

#ifdef  __cplusplus
}
#endif

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
private slots:
    void on_pushButton_File_clicked();
    void on_pushButton_Zip_clicked();
    void on_pushButton_UnZip_clicked();
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

4.mainWindow.cpp源码

void MainWindow::on_pushButton_File_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(
                this,//指定父窗口
                "选择文件",//打开文件对话框的标题
                 ".",//打开目录,"." 表示当前目录
                "txt Files (*.txt)"
                );
    if (filePath.isEmpty()) {
        ui->label_File->setText("");
    }else{
        ui->label_File->setText(filePath);
    }
}

void MainWindow::on_pushButton_Zip_clicked()
{
    QString srcfilePath = ui->label_File->text();
    if(srcfilePath == "") { return; }
    QString zipfilePath = srcfilePath.mid(0,srcfilePath.lastIndexOf(".")) + ".7z";
    ui->statusBar->showMessage("正在压缩,请稍后!");
    qDebug() << LzmaCompressFun(srcfilePath.toLatin1().data(),zipfilePath.toLatin1().data());
    ui->statusBar->showMessage("压缩完成!");
    ui->label_zip->setText(zipfilePath);
}
void MainWindow::on_pushButton_UnZip_clicked()
{
    QString srcfilePath = ui->label_zip->text();
    if(srcfilePath == "") { return; }
    QString unZipfilePath = srcfilePath.mid(0,srcfilePath.lastIndexOf(".")) + "_unZip.txt";
    ui->statusBar->showMessage("正在解压,请稍后!");
    qDebug() << LzmaUncompressFun(srcfilePath.toLatin1().data(),unZipfilePath.toLatin1().data());
    ui->statusBar->showMessage("解压完成!");
    ui->label_unZip->setText(unZipfilePath);
}

运行结果

运行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值