Qt下使用第三方开源库实现文件压缩(C++开源库zlib)

简述

前段时间有个项目需要将文件进行压缩处理,效率最高的当然是直接集成源码,调用接口函数。下面介绍如何使用开源库zlib,通过函数调用的方式实现文件压缩。

代码之路

在官网上下载zlib开源库代码,拷贝源码中的minizip文件夹到项目目录,添加minizip文件夹下的文件。

 minizip文件夹下有两种格式的文件,.h文件为头文件,.c文件为源文件,具体如下:
 头文件:crypt.h ioapi.h iowin32.h mztools.h unzip.h zconf.h zip.h zlib.h
 源文件:ioapi.c iowin32.c mztools.c unzip.c zip.c

编写接口类,接口类的主体有两个函数,一个压缩文件接口,一个解压文件接口。
接口类代码如下,首先是头文件:

//myzip.h
#include <QObject>
#include <QDebug>
#include "minizip/zip.h"
#include "minizip/unzip.h"
#include "minizip/iowin32.h"

#define MAX_BUFF_SIZE (1024*1024*100)

class Myzip : public QObject
{
  Q_OBJECT
public:
  Myzip();
  ~Myzip();

  //压缩文件 压缩单个文件
  void compressFile(QString srcfile, QString zipfile);

  //解压文件
  void uncompressFile(QStringList listfile, QString zipfile);

signals:
  void compressDone(QString filename);
};

然后是源文件:

//myzip.cpp
#include "myzip.h"
#pragma comment(lib, "zdll.lib")

Myzip::Myzip()
{

}
Myzip::~Myzip()
{

}

void Myzip::compressFile(QString srcfile, QString zipfile)
{
  //文件名格式转化
  QByteArray srcba = srcfile.toLocal8Bit();
  char* srcf = srcba.data(); //待压缩的原始文件
  QByteArray zipba = zipfile.toLocal8Bit();
  char* zipf = zipba.data(); //压缩包文件名
  QStringList tmplist = srcfile.split("/");
  QString zipinfile = tmplist.at(tmplist.size() - 1);
  QByteArray zipinba = zipinfile.toLocal8Bit();
  char* zipinf = zipinba.data(); //压缩包内文件名

  //初始声明
  FILE* fin;
  int size_read = 0;
  int size_buf = MAX_BUFF_SIZE;
  void* buf = (void*)malloc(size_buf);
  int err = 0;

  //压缩文件
  //新建压缩文件
  zipFile zf = zipOpen64(zipf, 0); //0或2
  if (zf != NULL)
  {
      //读原始文件信息
      zip_fileinfo zi;
      zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = zi.tmz_date.tm_mday \
              = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
      zi.dosDate = 0;
      zi.internal_fa = 0;
      zi.external_fa = 0;
      err = zipOpenNewFileInZip(zf, zipinf, &zi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);

      //读原始文件数据
      if (err != ZIP_OK)
      {
          qDebug() << "error in opening srcfile!";
      }
      else
      {
          fin = fopen(srcf, "rb");
          if (fin == NULL)
          {
              err = ZIP_ERRNO;

              zipClose(zf, NULL);
              free (buf);

              qDebug() << "error in opening srcfile for reading!";
              return;
          }
      }
      if (err == ZIP_OK)
      {
          size_read = (int)fread(buf, 1, size_buf, fin);
          if (size_read < size_buf)
          {
              if (feof(fin) == 0)
              {
                  qDebug() << "error in reading srcfile!";
                  err = ZIP_ERRNO;
              }
          }

          if (size_read > 0)
          {
              //压缩单个原始文件到zip包
              err = zipWriteInFileInZip(zf, buf, size_read);
              if (err < 0)
              {
                  qDebug() <<"error in writing in the zipfile.";
              }
          }
      }
      if (fin)
      {
          fclose(fin);
      }

      if (err < 0)
      {
          err = ZIP_ERRNO;
      }
      else
      {
          //关闭zip包中单个文件
          err = zipCloseFileInZip(zf);
          if (err != ZIP_OK)
              qDebug() << "error in closing in the zipfile.";
      }
  }

  //释放资源
  int errclose = zipClose(zf, NULL);
  if (errclose != ZIP_OK)
  {
      qDebug() << "error in closing zipfile itself.";
  }
  free(buf);

  //发送压缩完成信号
  emit compressDone(zipfile);
  return;
}

void Myzip::uncompressFile(QStringList listfile, QString zipfile)
{

}

压缩结束后,发送compressDone信号,表示压缩文件可以使用。

写在最后

代码中的压缩经过内存泄漏检测和长时间烤机运行,非常稳定。由于工程仅需要压缩文件,故没有提供解压文件的具体函数。

发布了47 篇原创文章 · 获赞 45 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/lusanshui/article/details/89846623