使用lzma SDK对7z文件简单解压缩有时候我们只需要单纯对lzma算法压缩的7z文件进行解压,有时需要在嵌入式设备上解压,使用p7zip虽然支持多种格式,但是不容易裁剪,使用lzma SDK是首选:
可以在这里找到各种版本:http://zh.sourceforge.jp/projects/sfnet_sevenzip/releases/
我下载了4.65版本,这个对文件名编码支持没有9.20的好,中文可能有问题,但是我的需求不需要支持中文文件名,所以足够用了。
解压后先看一下7z这个工程,这个示例只有文件解压操作,仿照就可以写一个更加精简的解压函数:
需要的文件可以参考实例:
修改7zMain.c即可。
我们的目的是写一个函数extract7z,接收参数是7z文件路径,输出文件路径,便可执行全部解压。
主要调用函数:
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
SRes SzAr_Extract(
const CSzArEx *p,
ILookInStream *inStream,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
我们先在Windows下编译:
完整代码如下:
/* 7zMain.c - Test application for 7z Decoder
*/
#include
#include
#include
#define LOGD printf
#define LOGE printf
#include "7zCrc.h"
#include "7zFile.h"
#include "7zVersion.h"
#include "7zAlloc.h"
#include "7zExtract.h"
#include "7zIn.h"
int MY_CDECL extract7z(const char* srcFile, const char* dstPath)
{
CFileInStream archiveStream;
CLookToRead lookStream;
CSzArEx db;
SRes res;
ISzAlloc allocImp;
ISzAlloc allocTempImp;
char outPath[1024] = { 0 };
LOGD("7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n");
if (InFile_Open(&archiveStream.file, srcFile)) {//open 7z file
LOGE("can not open input file\n");
return 1;
}
FileInStream_CreateVTable(&archiveStream);
LookToRead_CreateVTable(&lookStream, False);
lookStream.realStream = &archiveStream.s;
LookToRead_Init(&lookStream);
allocImp.Alloc = SzAlloc;
allocImp.Free = SzFree;
allocTempImp.Alloc = SzAllocTemp;
allocTempImp.Free = SzFreeTemp;
CrcGenerateTable();
SzArEx_Init(&db);
res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if(res == SZ_OK)
{
Int32 i;
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
LOGD("Total file/directory count[%d]\n", db.db.NumFiles);
for (i = db.db.NumFiles - 1; i >= 0; i--) {
size_t offset;
size_t outSizeProcessed;
CSzFileItem *f = db.db.Files + i;
strcpy(outPath, dstPath);
strcat(outPath, "/");
strcat(outPath, f->Name);
if (f->IsDir) { //dir
LOGD("dir [%s]\n", outPath);
mkdir(outPath);
continue;
}else{ //file
LOGD("file [%s]\n", outPath);
res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex,
&outBuffer, &outBufferSize, &offset, &outSizeProcessed,
&allocImp, &allocTempImp);
if (res != SZ_OK){
break;
}else{
CSzFile outFile;
size_t processedSize;
if (OutFile_Open(&