如何获取LZMA2文件(.xz / liblzma)的未压缩大小?

5

我正在寻找一种方法来获取使用xz工具压缩的LZMA2 / .xz文件的未压缩流大小。

为此任务,我将使用Windows / Linux中的liblzma,因此我想找到一些在liblzma中的C / C ++ API可以完成这个任务。

2个回答

6

我认为我已经找到了一个解决方案。

这是一个非常简单的代码示例,但似乎可以很好地工作。

我假设我有一个 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;
}

我想使用lzma2本地库来编写Hadoop压缩编解码器。如果您有任何API文档或在压缩/解压相关理解方面的帮助,将非常有帮助。 - samarth
两个问题。 (1) 在调用 lzma_index_buffer_decode 之前,您需要初始化 memlimit ,否则在某些情况下它会返回 LZMA_MEMLIMIT_ERROR 。 (2) 不应该调用 lzma_index_initindex 的初始值将被 lzma_index_buffer_decode 忽略。 - Patrick
是的 Patrick,将12替换为LZMA_STREAM_HEADER_SIZE,“流头和流尾具有相同的大小”,请参见lzma/stream_flags.h。 - Stephane

0

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是未压缩数据的大小。


1
我认为XZ文件格式不是纯粹的LZMA格式,而是一种包装多种压缩算法的格式。 - Dietrich Epp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接