C LZMA SDK:LZMA2压缩文件的解压缩功能
发布时间:2020-12-16 07:07:22 所属栏目:百科 来源:网络整理
导读:我正在尝试创建一个解压缩LZAM2压缩数据的函数.我从 this tutorial开始自我灵感,这对LZMA非常有用,我试图将它改编为LZMA2.我成功地为LZMA2创建了压缩功能,但是我没有成功解压缩. 这是压缩功能: static void Compress2Inc(std::vectorunsigned char outBuf,c
我正在尝试创建一个解压缩LZAM2压缩数据的函数.我从
this tutorial开始自我灵感,这对LZMA非常有用,我试图将它改编为LZMA2.我成功地为LZMA2创建了压缩功能,但是我没有成功解压缩.
这是压缩功能: static void Compress2Inc(std::vector<unsigned char> &outBuf,const std::vector<unsigned char> &inBuf) { CLzma2EncHandle enc = Lzma2Enc_Create(&SzAllocForLzma,&SzAllocForLzma2); assert(enc); CLzma2EncProps props; Lzma2EncProps_Init(&props); props.lzmaProps.writeEndMark = 1; // 0 or 1 SRes res = Lzma2Enc_SetProps(enc,&props); assert(res == SZ_OK); unsigned propsSize = LZMA_PROPS_SIZE; outBuf.resize(propsSize); res = Lzma2Enc_WriteProperties(enc); //cout << res; //assert(res == SZ_OK && propsSize == LZMA_PROPS_SIZE); VectorInStream inStream = { &VectorInStream_Read,&inBuf,0 }; VectorOutStream outStream = { &VectorOutStream_Write,&outBuf }; res = Lzma2Enc_Encode(enc,(ISeqOutStream*)&outStream,(ISeqInStream*)&inStream,0); assert(res == SZ_OK); Lzma2Enc_Destroy(enc); } 哪里: static void *AllocForLzma2(void *,size_t size) { return BigAlloc(size); } static void FreeForLzma2(void *,void *address) { BigFree(address); } static ISzAlloc SzAllocForLzma2 = { AllocForLzma2,FreeForLzma2 }; static void *AllocForLzma(void *,size_t size) { return MyAlloc(size); } static void FreeForLzma(void *,void *address) { MyFree(address); } static ISzAlloc SzAllocForLzma = { AllocForLzma,FreeForLzma }; typedef struct { ISeqInStream SeqInStream; const std::vector<unsigned char> *Buf; unsigned BufPos; } VectorInStream; SRes VectorInStream_Read(void *p,void *buf,size_t *size) { VectorInStream *ctx = (VectorInStream*)p; *size = min(*size,ctx->Buf->size() - ctx->BufPos); if (*size) memcpy(buf,&(*ctx->Buf)[ctx->BufPos],*size); ctx->BufPos += *size; return SZ_OK; } typedef struct { ISeqOutStream SeqOutStream; std::vector<unsigned char> *Buf; } VectorOutStream; size_t VectorOutStream_Write(void *p,const void *buf,size_t size) { VectorOutStream *ctx = (VectorOutStream*)p; if (size) { unsigned oldSize = ctx->Buf->size(); ctx->Buf->resize(oldSize + size); memcpy(&(*ctx->Buf)[oldSize],buf,size); } return size; } 这是我到目前为止使用uncompression函数,但Lzma2Dec_DecodeToBuf函数返回错误代码1(SZ_ERROR_DATA),我在网上找不到任何关于此的内容. static void Uncompress2Inc(std::vector<unsigned char> &outBuf,const std::vector<unsigned char> &inBuf) { CLzma2Dec dec; Lzma2Dec_Construct(&dec); SRes res = Lzma2Dec_Allocate(&dec,outBuf.size(),&SzAllocForLzma); assert(res == SZ_OK); Lzma2Dec_Init(&dec); outBuf.resize(UNCOMPRESSED_SIZE); unsigned outPos = 0,inPos = LZMA_PROPS_SIZE; ELzmaStatus status; const unsigned BUF_SIZE = 10240; while (outPos < outBuf.size()) { unsigned destLen = min(BUF_SIZE,outBuf.size() - outPos); unsigned srcLen = min(BUF_SIZE,inBuf.size() - inPos); unsigned srcLenOld = srcLen,destLenOld = destLen; res = Lzma2Dec_DecodeToBuf(&dec,&outBuf[outPos],&destLen,&inBuf[inPos],&srcLen,(outPos + destLen == outBuf.size()) ? LZMA_FINISH_END : LZMA_FINISH_ANY,&status); assert(res == SZ_OK); inPos += srcLen; outPos += destLen; if (status == LZMA_STATUS_FINISHED_WITH_MARK) break; } Lzma2Dec_Free(&dec,&SzAllocForLzma); outBuf.resize(outPos); } 我正在使用从here下载的Visual Studio 2008和LZMA SDK.有人here有完全相同的问题,但我无法使用他的代码…… 有没有人使用LZMA SDK成功解压缩LZMA2压缩文件? 请帮忙! 解决方法
一个临时的解决方法是替换SRes res = Lzma2Dec_Allocate(& dec,& SzAllocForLzma);使用SRes res = Lzma2Dec_Allocate(& dec,8,& SzAllocForLzma);在Uncompress2Inc函数中,其中8是幻数…
然而,这不是解决问题的正确方法…… 第一个错误是Lzma2Enc_WriteProperties不返回结果,而是返回属性字节,该字节必须用作Uncompress2Inc函数中Lzma2Dec_Allocate调用的第二个参数.因此,我们用属性字节替换幻数8,一切都按预期工作. 为了实现这一点,必须将5字节标题添加到将在解码功能中提取的编码数据中.这是一个可以在VS2008中运行的示例(不是最完美的代码,但它可以工作……我会稍后回来,当我有时间时,有一个更好的例子): void Lzma2Benchmark::compressChunk(std::vector<unsigned char> &outBuf,const std::vector<unsigned char> &inBuf) { //! todo This is a temporary workaround,size needs to be added to the m_uncompressedSize = inBuf.size(); std::cout << "Uncompressed size is: " << inBuf.size() << std::endl; DWORD tickCountBeforeCompression = GetTickCount(); CLzma2EncHandle enc = Lzma2Enc_Create(&m_szAllocForLzma,&m_szAllocForLzma2); assert(enc); CLzma2EncProps props; Lzma2EncProps_Init(&props); props.lzmaProps.writeEndMark = 1; // 0 or 1 props.lzmaProps.level = 9; props.lzmaProps.numThreads = 3; //props.numTotalThreads = 2; SRes res = Lzma2Enc_SetProps(enc,&props); assert(res == SZ_OK); // LZMA_PROPS_SIZE == 5 bytes unsigned propsSize = LZMA_PROPS_SIZE; outBuf.resize(propsSize); // I think Lzma2Enc_WriteProperties returns the encoding properties in 1 Byte Byte properties = Lzma2Enc_WriteProperties(enc); //! todo This is a temporary workaround m_propByte = properties; //! todo Here m_propByte and m_uncompressedSize need to be added to outBuf's 5 byte header so simply add those 2 values to outBuf and start the encoding from there. BenchmarkUtils::VectorInStream inStream = { &BenchmarkUtils::VectorInStream_Read,0 }; BenchmarkUtils::VectorOutStream outStream = { &BenchmarkUtils::VectorOutStream_Write,0); std::cout << "Compress time is: " << GetTickCount() - tickCountBeforeCompression << " milliseconds.n"; assert(res == SZ_OK); Lzma2Enc_Destroy(enc); std::cout << "Compressed size is: " << outBuf.size() << std::endl; } void Lzma2Benchmark::unCompressChunk(std::vector<unsigned char> &outBuf,const std::vector<unsigned char> &inBuf) { DWORD tickCountBeforeUncompression = GetTickCount(); CLzma2Dec dec; Lzma2Dec_Construct(&dec); //! todo Heere the property size and the uncompressed size need to be extracted from inBuf,which is the compressed data. // The second parameter is a temporary workaround. SRes res = Lzma2Dec_Allocate(&dec,m_propByte/*8*/,&m_szAllocForLzma); assert(res == SZ_OK); Lzma2Dec_Init(&dec); outBuf.resize(m_uncompressedSize); unsigned outPos = 0,inPos = LZMA_PROPS_SIZE; ELzmaStatus status; const unsigned BUF_SIZE = 10240; while(outPos < outBuf.size()) { SizeT destLen = std::min(BUF_SIZE,outBuf.size() - outPos); SizeT srcLen = std::min(BUF_SIZE,inBuf.size() - inPos); SizeT srcLenOld = srcLen,&status); assert(res == SZ_OK); inPos += srcLen; outPos += destLen; if(status == LZMA_STATUS_FINISHED_WITH_MARK) { break; } } Lzma2Dec_Free(&dec,&m_szAllocForLzma); outBuf.resize(outPos); std::cout << "Uncompress time is: " << GetTickCount() - tickCountBeforeUncompression << " milliseconds.n"; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- ruby – 在Rails模型中around_create回调的目的是什么?
- 使用ajax异步提交表单的几种方法总结
- J-Flah ARM配置2440
- ReactiveCocoa
- ruby-on-rails – 从Ruby on Rails 3.2.6中的Paperclip生成
- objective-c – ‘NSAutoreleasePool’可能无法响应Ubuntu上
- xmlHttpRequest的status的值的含义
- c# – 进度条工作但标签未更新
- c# – 使用linq Group运算符展平查询结果的正确方法是什么
- objective-c – _PFBatchFaultingArray objectAtIndex: