LZMA декодирование данных BLOB из БД

В БД Oracle имеются BLOB файлы, которые по сути являются закодированными lzma std::vector float. В коде(RAD Studio) в конце вопроса представлены исходники(ни документации ни оригинальных коментариев не сохранилось, чуток изменил имена объектов, для удобоваримости) старой загрузки данных в таблицы БД. Насколько я понимаю упрощенно это происходит примерно так:

  1. Байты вектора float (в форме TStream) кодируются lzma
  2. К кодированным данным добавляются байты ("BF" и enum)
  3. Затем идет запись в таблицу БД

При помощи cx_Oracle в Python я выгружаю эти данные, ниже представлены первые 50 байт как пример: b'BF\x01\xdc\r\x00\x00]\x00\x00@\x00\x00a\x99\x0bD\x11\xe0\xcc\xa4\xb3Rj\xe0\x01\xcf\x05`\xe7\xe1_q~V\xc3\xe8\xfd\r\r\xa7w\xf0\x01^\xf49t\x99\xaa'

В данных байтах явно отмечается приписка "BF", далее при помощи стандартного модуля lzma я пытаюсь раскодировать данные из БД, что бы получить байтовое представление vectorа, однако, я получаю ошибку

rows = cursor.fetchall()
temp = rows[0][4].read()
lzma.decompress(temp, format=lzma.FORMAT_RAW, filters=[{"id": lzma.FILTER_LZMA2}])

_lzma.LZMAError: Corrupt input data

Я пытался: 1)покопаться в исходниках ULZMAEncoder (код на паскале) что бы понять, какие фильтры надо задать в decompress, но ни к чему не пришел 2) пытался "отрезать" 1-20 первых байтов, с последующей попыткой декомпресии, что привело к некоторым удачным декомпрессиям, однако результат давал пустые байты b''

У меня 2 вопроса:

  1. Как нужно задать параметры фильтров lzma что бы эти данные считались?
  2. если все же удастся считать байты vector floatов, то что почитать, что бы понять как привести их в формат, понятный Python?

Заранее спасибо за помощь!

Старый код:

#include<ULZMAEncoder.hpp>

...
const int PrefixSize = 1;
const int SignatureSize = 2;
const int G01SA3DA9 = 4;
unsigned char G01SA3DAF[SignatureSize] = "BF";
static std::auto_ptr<TLZMAEncoder>G01SA3DB0(NULL); // ниже в коде - Encoder

...

enum G01SA3DB8
{
  G01SA3DB9 = 0x00, G01SA3DBA = 0x01, G01SA3DBB = 0x02
};

 static void Func_1(TStream*inPut, TStream*aOutput)
  {
    aOutput->Size = 0;
    if (inPut->Size == 0)
      return;
    inPut->Position = 0;
    if (inPut->Size >= 20)
    {
      Func_2(inPut->Size, aOutput);
      Encoder()->Code(inPut, aOutput, -1, -1); // ptr на TLZMAEncoder, само кодирование потока ВРОДЕ происходит прямо тут
      if ((inPut->Size + GetHeaderSize(G01SA3DBB)) <= aOutput->Size) // судя по всему проверка размеров потоков, G01SA3DBB = 0x02
      {
        aOutput->Size = 0;
        Func_3(inPut, aOutput);
      }
    }
    else
      Func_3(inPut, aOutput);
  }

  static void Func_2(unsigned int aDataSize, TStream*aStream)
  {
    Func_4(G01SA3DBA, aStream); // G01SA3DBA = 0x01
    aStream->Write(&aDataSize, G01SA3DA9); // G01SA3DA9 = 4;
    Encoder()->WriteCoderProperties(aStream); // Или же здесь задаются параметры записи? только как понять какие они?
  }

  static void Func_3(TStream*inPut, TStream*aOutput)
  {
    Func_4(G01SA3DBB, aOutput); // G01SA3DBB = 0x02
    inPut->Position = 0;
    aOutput->CopyFrom(inPut, inPut->Size);
  }

  static void Func_4(G01SA3DB8 G01SA3DC5, TStream*aStream) // G01SA3DB8 - enum (выше)
  {
    aStream->Write(G01SA3DAF, SignatureSize); // Запись 2 байтов в aStream (то есть "BF", насколько я понимаю)
    aStream->Write(&G01SA3DC5, PrefixSize);  // Запись 1 байта в в aStream из enum в начале кода
  }
    
...

Ответы (0 шт):