Как получить несжатый размер файла LZMA2 (.xz / liblzma) - PullRequest
4 голосов
/ 31 января 2010

Я ищу способ получить размер несжатого потока файла LZMA2 / .xz, сжатого с помощью утилиты xz.

Я использую liblzma из Windows / Linux для этой задачи, поэтому мне кажется, что я ищу какой-нибудь C / C ++ API в liblzma, который бы сработал.

Ответы [ 2 ]

5 голосов
/ 01 февраля 2010

Я думаю, что нашел решение.

Это очень грубый пример кода, но, кажется, работает нормально.

Я предполагаю, что у меня есть функция do_mmap (), которая отображает весь файл как доступный только для чтения в память и возвращает отображенный общий размер. Естественно, это можно адаптировать для использования read / fread / ReadFile или любого другого File 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;
}
0 голосов
/ 31 января 2010

Скачав источник из 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 - это размер несжатых данных.

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

...