LINUX.ORG.RU

Десериализация сырых данных

 


0

1

Надо мне сохранить некие данные, а позже прочитать их той же программой.

struct data *data;
write (f, data, size_of_data);
...
read (f, data, size_of_data);
Сберег природу.

Если кто-то не знает, что так делать нельзя, сообщаю - так делать нельзя. Если кто-то захочет сообщить в этой теме, что так делать нельзя, то не надо - это оффтоп, заводите свои темы.

Я хочу поговорить, как так сделать!

Чтобы успешно прочесть такие данные, потребуется заголовок с метаданными (описание структуры, как она представляется в оперативной памяти) и десериализатор, который по метаданным декодирует данные в случае несовпадения представления данных в памяти записавшего с прочитавшим.

current = meta_current ();
write (f, current, size_of_meta (current));
...
meta = meta_read (f);
read (f, data, size_of_data (current));
if (!meta_eq (meta, current)) meta_decode (meta, data);

Что нужно предусмотреть в этом случае?

  • указатели относительные
  • порядок байт
  • размер элементарных типов данных
  • смещение всех элементов структуры
  • как узнать определить два предыдущих пункта не компилируя и не запуская тест
  • текстовое описание структуры или его хэш

Что еще?

Числа с плавающей точкой мне не надо, но послушать про них будет интересно.

Магией в meta_decode и вопросом, кто будет писать эту функцию можно пренебречь.

★★

Последнее исправление: fopen (всего исправлений: 1)

как узнать определить два пункта не компилируя и не запуская тест
текстовое описание структуры или его хэш

Что это значит?

fmap
()
Ответ на: комментарий от anonymous

Не то. Я хочу вообще обойтись без сериализации - десериализации в основном сценарии использования программы.

fopen ★★
() автор топика
Ответ на: комментарий от fmap

два предыдущих пункта (опечатка)

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

fopen ★★
() автор топика

Я вот только недавно проклинал себя, пытаясь разобрать данные, подобным образом записанные на 32-битной машине, на своей 64-битной. И, вроде бы, ведь везде делал uint64_t и т.п., а оказалось, что проблема была в time_t (естественно, еще пришлось указать явно выравнивание по 4 байта). Явная замена его на uint32_t временно решила проблему. НО! При переходе на другую архитектуру опять всплывет жесть.

Советую в структуру с данными добавить одно неиспользуемое поле (скажем, uint16_t) — маркер конца структуры.

Не забывай про выравнивание. И лучше сразу подумай про функции вроде htons (man endian), чтобы смена архитектуры не добавила геморроя.

Да, если данных много, то храни еще дополнительный файлик со смещениями (тупо: ключ/смещение). Тогда будет проще и быстрей искать.

Anon
()
Ответ на: комментарий от Anon

Япона мать!

Какой же я дурак!

И вот почему умная мысля приходит опосля? Уже наплодил кучу велосипедов, и только сейчас придумал добавлять в структуры метку! Во болван, блин!

Можно, кстати, уменьшить размер файла: просто в начало добавлять описание (маркер для определения "конечности" + размер блока данных).

Anon
()
Ответ на: комментарий от Gvidon

Потому что "птичка улетела": уже больше пары сотен мегабайт данных накопилось, а на 32-битной системе как раз выравнивание по 4. Лень их переформатировать.

Anon
()

man xdr, man ei, man protobuf, тысячи их.

nanoolinux ★★★★
()

Определить little endian или big endian можно по маркеру аля BOM. Стуктуру читать не целиком а по полям.

Или читать побайтово и склеивать самому.

andreyu ★★★★★
()
Ответ на: комментарий от Gvidon

Парни, не увлекайтесь этим. Спарки, конечно, померли, да здравствует x86, но мало ли как оно в жизни бывает.

Хинт: спарк - одна из тех архитектур, в которых чтение невыровненных данных не возможно в принципе. Ну, то есть, если компилятор позаботится и обернёт ваш *misalignedIntPtr = 0; в серию приседаний - вам повезёт. А иначе - сегфолт.

Ну и «приседания» - это тоже, очевидно, не гуд по производительности.

AlexM ★★★★★
()
Последнее исправление: AlexM (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.