`
hzy3774
  • 浏览: 984380 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

C语言编程使用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
 2008-11-23 : Igor Pavlov : Public domain */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#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(&outFile, outPath)) {
						LOGE("can not open output file\n");
						res = SZ_ERROR_FAIL;
						break;
					}
					processedSize = outSizeProcessed;
					if (File_Write(&outFile, outBuffer + offset, &processedSize)
							!= 0 || processedSize != outSizeProcessed) {
						LOGE("can not write output file\n");
						res = SZ_ERROR_FAIL;
						break;
					}
					if (File_Close(&outFile)) {
						LOGE("can not close output file\n");
						res = SZ_ERROR_FAIL;
						break;
					}
				}
			}
		}
		IAlloc_Free(&allocImp, outBuffer);
	}
	SzArEx_Free(&db, &allocImp);

	File_Close(&archiveStream.file);
	if (res == SZ_OK)
	{
		LOGD("Everything is Ok\n");
		return 0;
	}
	if (res == SZ_ERROR_UNSUPPORTED
		)
		LOGE("decoder doesn't support this archive\n");
	else if (res == SZ_ERROR_MEM
		)
		LOGE("can not allocate memory\n");
	else if (res == SZ_ERROR_CRC
		)
		LOGE("CRC error\n");
	else
		LOGE("ERROR #%d\n", res);
	return 1;
}

int main(int numargs, char *args[])
{
	return extract7z(args[1], args[2]);
}

 

我用的是Eclipse,使用Mingw编译。

 

 

执行效果,能正确解压。

这样的解压只能适用简单的解压,不支持加密,参数2的输出文件路径中的所有文件夹都必须存在,压缩包中文件夹不需要存在,解压时会自动创建。

压缩包中的文件夹不能为中文,否则乱码。



 

  • 大小: 6.9 KB
  • 大小: 51.3 KB
  • 大小: 41.8 KB
分享到:
评论
1 楼 xiaoyun311 2015-08-24  
求问有没有函数能在解压前判断压缩文件是否加密?

相关推荐

Global site tag (gtag.js) - Google Analytics