在C中使用C-LZMA-SDK解压缩LZMA返回SZ_ERROR_DATA,因为输入流的第一个字节是!= 0

我有一个文件,根据它的拥有者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()开始解码的偏移量.

点赞