环境
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);
}
运行结果
运行结果如下: