我正在寻找一种方法来获取使用xz工具压缩的LZMA2 / .xz文件的未压缩流大小。
为此任务,我将使用Windows / Linux中的liblzma,因此我想找到一些在liblzma中的C / C ++ API可以完成这个任务。
我认为我已经找到了一个解决方案。
这是一个非常简单的代码示例,但似乎可以很好地工作。
我假设我有一个 do_mmap() 函数,将整个文件映射为只读,并返回映射的总大小。 这自然可以适应使用 read/fread/ReadFile 或任何其他文件 API。
extern size_t get_uncompressed_size(const char *filename)
{
lzma_stream_flags stream_flags;
int file_size;
const uint8_t *data = (uint8_t *) do_mmap(filename, &file_size);
// 12 is the size of the footer per the file-spec...
const uint8_t *footer_ptr = data + file_size - 12;
// Something is terribly wrong
if (footer_ptr < data) {
do_unmap((void *)data, file_size);
return -1;
}
// Decode the footer, so we have the backward_size pointing to the index
lzma_stream_footer_decode(&stream_flags, (const uint8_t *)footer_ptr);
// This is the index pointer, where the size is ultimately stored...
const uint8_t *index_ptr = footer_ptr - stream_flags.backward_size;
// Allocate an index
lzma_index *index = lzma_index_init(NULL);
uint64_t memlimit;
size_t in_pos = 0;
// decode the index we calculated
lzma_index_buffer_decode(&index, &memlimit, NULL, index_ptr, &in_pos, footer_ptr - index_ptr);
// Just make sure the whole index was decoded, otherwise, we might be
// dealing with something utterly corrupt
if (in_pos != stream_flags.backward_size) {
do_unmap((void *)data, file_size);
lzma_index_end(index, NULL);
return -1;
}
// Finally get the size
lzma_vli uSize = lzma_index_uncompressed_size(index);
lzma_index_end(index, NULL);
return (size_t) uSize;
}
从sourceforge下载源代码并查看后,我从主头文件LzmaLib.h中引用了以下内容
/*
LzmaUncompress
--------------
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
Out:
destLen - processed output size
srcLen - processed input size
Returns:
SZ_OK - OK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation arror
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src)
*/
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
const unsigned char *props, size_t propsSize);
看起来destLen
是未压缩数据的大小。
lzma_index_buffer_decode
之前,您需要初始化memlimit
,否则在某些情况下它会返回LZMA_MEMLIMIT_ERROR
。 (2) 不应该调用lzma_index_init
。index
的初始值将被lzma_index_buffer_decode
忽略。 - Patrick