У меня есть уже существующая база данных Беркли, записанная и прочитанная из программы, написанной на C++. Мне нужно обойти использование этой программы и писать в базу данных напрямую с помощью python.
Я могу это сделать, но у меня чертовски много времени, чтобы правильно закодировать мои данные, чтобы они были в правильной форме и затем могли быть прочитаны исходной программой C++. На самом деле, я не могу понять, как декодировать существующие данные, когда я знаю, что это за значения.
Ключи пар ключ-значение в базе данных должны иметь метки времени в форме ГГГГММДДЧЧммСС. Значения должны быть пятью двойными и целочисленными, смешанными вместе, под которыми я подразумеваю (из исходного кода программы C++) следующую структуру (?) DVALS
typedef struct
{
double d1;
double d2;
double d3;
double d4;
double d5;
int i1;
} DVALS;
записывается в базу данных как значение пары ключ-значение следующим образом:
DBT data;
memset(&data, 0, sizeof(DBT));
DVALS dval;
memset(&dval, 0, sizeof(DVALS));
data.data = &dval;
data.size = sizeof(DVALS);
db->put(db, NULL, &key, &data, 0);
К счастью, я могу знать, каковы значения. Итак, если я запускаю из командной строки
db_dump myfile
последняя запись такая:
323031393033313431353533303000
ae47e17a140e4040ae47e17a140e4040ae47e17a140e4040ae47e17a140e40400000000000b6a4400000000000000000
Используя модуль Python bsddb3, я также могу вытащить эту запись:
from bsddb3 import db
myDB = db.DB()
myDB.open('myfile', None, db.DB_BTREE)
cur = myDB.cursor()
kvpair = cur.last()
Теперь kvpair содержит следующую информацию:
(b'20190314155300\x00', b'\xaeG\xe1z\x14\x0e@@\xaeG\xe1z\x14\x0e@@\xaeG\xe1z\x14\x0e@@\xaeG\xe1z\x14\x0e@@\x00\x00\x00\x00\x00\xb6\xa4@\x00\x00\x00\x00\x00\x00\x00\x00')
Временная метка легко читается, и в этом случае фактические значения следующие:
d1 = d2 = d3 = d4 = 32.11
d5 = 2651
i1 = 0
Поскольку последовательность '\xaeG\xe1z\x14\x0e@@' повторяется 4 раза, я думаю, что она соответствует значению 32,11.
Поэтому я думаю, что мой вопрос может быть просто о кодировании/декодировании, но, возможно, это еще не все, отсюда и предыстория.
kvpair[1].decode('utf-8')
Использование различных кодировок просто дает ошибки, подобные этой:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xae in position 0: invalid start byte






Данные значения являются двоичными, поэтому их можно распаковать с помощью модуля Python структура.
>>> import struct
>>> bs = b'\xaeG\xe1z\x14\x0e@@\xaeG\xe1z\x14\x0e@@\xaeG\xe1z\x14\x0e@@\xaeG\xe1z\x14\x0e@@\x00\x00\x00\x00\x00\xb6\xa4@\x00\x00\x00\x00\x00\x00\x00\x00'
>>> len(bs)
48
>>> struct.unpack('<5di4x', bs)
(32.11, 32.11, 32.11, 32.11, 2651.0, 0)
struct.unpack принимает два аргумента: спецификатор формата, который определяет формат и типы данных, а также данные для распаковки. Формат '<5di4x' описывает:
<: обратный порядок байтов5d: пять удвоений (по 8 байт)i: одно целое число со знаком (4 байта; I для беззнакового)4x: четыре байта заполненияТаким же образом можно упаковать данные, используя struct.pack.
>>> nums = [32.11, 32.11, 32.11, 32.11, 2651, 0]
>>> format_ = '5di4x'
>>> packed = struct.pack(format_, *nums)
>>> packed == bs
True
>>>
вы должны быть точны в своих вопросах и опускать предысторию