Кодирование/декодирование (записи базы данных Беркли) в python3

У меня есть уже существующая база данных Беркли, записанная и прочитанная из программы, написанной на 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

вы должны быть точны в своих вопросах и опускать предысторию

Anga 16.03.2019 23:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
268
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Данные значения являются двоичными, поэтому их можно распаковать с помощью модуля 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
>>> 

Другие вопросы по теме