我有一个文件,根据它的拥有者LZMA压缩.
lzmadecode.exe(程序)没有问题解码它,所以文件没有损坏,似乎确实是LZMA编码.
这是我将文件读取到缓冲区并调用UnCompress函数的代码:
int main()
{
::std::ifstream lReplayFileStream("C:\\tmp\\COMPRESSED_FILE", ::std::ios::binary);
if (lReplayFileStream)
{
lReplayFileStream.seekg(0, lReplayFileStream.end);
std::streamoff lFileSize = lReplayFileStream.tellg();
lReplayFileStream.seekg(0, lReplayFileStream.beg);
char * lReplayBuffer = new char[lFileSize];
lReplayFileStream.read(lReplayBuffer, lFileSize);
if (lReplayFileStream.gcount() != lFileSize)
{
// Error
}
lReplayFileStream.close();
::std::vector<unsigned char> inBuf(lFileSize);
::std::vector<unsigned char> outBuf;
memcpy(&inBuf[0], lReplayBuffer, lFileSize);
UNCOMPRESSED_SIZE = lFileSize + lFileSize * 3;
UnCompress(outBuf, inBuf);
delete[] lReplayBuffer;
}
return EXIT_SUCCESS;
}
这是UnCompress功能(不是我写的,是我从互联网上获得的一个例子):
static void UnCompress(std::vector<unsigned char> &outBuf, const std::vector<unsigned char> &inBuf)
{
outBuf.resize(UNCOMPRESSED_SIZE);
unsigned dstLen = outBuf.size();
unsigned srcLen = inBuf.size() - LZMA_PROPS_SIZE;
SRes res = LzmaUncompress(&outBuf[0], &dstLen, &inBuf[LZMA_PROPS_SIZE], &srcLen, &inBuf[0], LZMA_PROPS_SIZE);
outBuf.resize(dstLen); // If uncompressed data can be smaller
}
该文件以以下字节开头:
5D 00 00 20 00 B6 EC 07 00
或者用ASCII:]. . . ¶ 一世 . .
LZMA_PROPS_SIZE始终为5.
正如您在UnCompress函数中看到的那样,inBuf被传递给LzmaUncompress()函数,偏移量为LZMA_PROP_SIZE,可能是标题?
我调试了代码并发现,在LzmaUncompress()的子例程中,如果inBuf [0]!= 0则检查它,如果是,则返回SZ_ERROR_DATA.
Screenshot where the error happens
如您所见,p-> tmpBuf [0]的字节(即inBuf)是¶,它是十六进制B6.这是inBuf的第6个字节,因为inBuf LZMA_PROP_SIZE(5).
我真的不太了解LZMA,但为什么LZMA_PROP_SIZE之后的第一个字节必须为0,为什么lzmadecompress.exe解压缩它,当它使用相同的功能?
我究竟做错了什么?
最佳答案 解
LZMA_PROP_SIZE之后的下一个8字节是未压缩数据的大小,因此是标头的一部分.程序失败,因为我试图解码文件,前8个字节是标题的一部分.
要解决这个问题,我只需要编辑这两行:
unsigned srcLen = inBuf.size() - LZMA_PROPS_SIZE - 8;
SRes res = LzmaUncompress(&outBuf[0], &dstLen, &inBuf[LZMA_PROPS_SIZE + 8], &srcLen, &inBuf[0], LZMA_PROPS_SIZE);
>从srcLen中减去8个字节
>将8字节添加到LzmaUncompress()开始解码的偏移量.