LZMA декодирование данных BLOB из БД
В БД Oracle имеются BLOB файлы, которые по сути являются закодированными lzma std::vector float. В коде(RAD Studio) в конце вопроса представлены исходники(ни документации ни оригинальных коментариев не сохранилось, чуток изменил имена объектов, для удобоваримости) старой загрузки данных в таблицы БД. Насколько я понимаю упрощенно это происходит примерно так:
- Байты вектора float (в форме TStream) кодируются lzma
- К кодированным данным добавляются байты ("BF" и enum)
- Затем идет запись в таблицу БД
При помощи 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 вопроса:
- Как нужно задать параметры фильтров lzma что бы эти данные считались?
- если все же удастся считать байты 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 в начале кода
}
...