简述
前段时间有个项目需要将文件进行压缩处理,效率最高的当然是直接集成源码,调用接口函数。下面介绍如何使用开源库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信号,表示压缩文件可以使用。
写在最后
代码中的压缩经过内存泄漏检测和长时间烤机运行,非常稳定。由于工程仅需要压缩文件,故没有提供解压文件的具体函数。