C ++ сериализация сложных данных с использованием Boost - PullRequest
2 голосов
/ 17 февраля 2009

У меня есть набор классов, из которых я хочу сериализовать данные. Однако данных много (мы говорим о std :: map с числом экземпляров классов до миллиона).

Не желая оптимизировать мой код слишком рано, я подумал, что попробую простую и чистую реализацию XML, поэтому я использовал tinyXML для сохранения данных в XML, но это было слишком медленно. Итак, я начал смотреть на использование Boost.Serialization для записи и чтения стандартного ascii или двоичного кода.

Похоже, что она лучше подходит для этой задачи, поскольку мне не нужно выделять всю эту память как накладные расходы, прежде чем я начну.

Мой вопрос заключается в том, как спланировать оптимальную стратегию сериализации для формата файла. Я не особенно хочу сериализовать всю карту, если в этом нет необходимости, так как на самом деле это только содержание, которое мне нужно. Немного поигравшись с сериализацией (и посмотрев на вывод), я не понимаю, как загрузка данных обратно могла бы знать, когда, например, будет достигнут конец карты, если я просто сохраню все элементы один за другим , Какие вопросы необходимо учитывать при планировании стратегии сериализации?

Спасибо.

Ответы [ 5 ]

4 голосов
/ 17 февраля 2009

Читать это FAQ ! Это помогает начать?

3 голосов
/ 23 февраля 2009

Есть много преимуществ для boost.serialization. Например, как вы говорите, просто включение метода с указанной сигнатурой позволяет платформе сериализовать и десериализовать ваши данные. Кроме того, boost.serialization включает в себя сериализаторы и считыватели для всех стандартных контейнеров STL, поэтому вам не нужно беспокоиться о том, все ли ключи были сохранены (будут) или как определить последнюю запись в карте при десериализации (это будет определяется автоматически).

Однако есть некоторые соображения. Например, если у вас есть поле в вашем классе, которое оно рассчитывает или использует для ускорения, например, индексы или хеш-таблицы, вам не нужно хранить их, , но вы должны взять с учетом того, что вы должны восстановить эти структуры по данным, считанным с диска.

Что касается "формата файла", который вы упоминаете, я думаю, что иногда мы пытаемся сосредоточиться на формате, а не на данных. Я имею в виду, точный формат файла не имеет значения, если вы можете без проблем извлекать данные, используя, скажем, boost.serialization. Если вы хотите поделиться файлом с другими утилитами, которые не используют сериализацию, это другое дело. Но только для (де) сериализации вам не нужно заботиться о внутреннем формате файла.

1 голос
/ 21 февраля 2009

Используйте Google Protocol Buffers , который является независимым от языка, платформо-независимым и расширяемым способом сериализации структурированных данных для использования в протоколах связи, хранения данных и многого другого. Google использует буфер протоколов почти для всех своих внутренних протоколов RPC и форматов файлов.

Существуют привязки для C ++, Java, Python, Perl, C # и Ruby.

Вы описываете свои данные в метаданных .proto файлов

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

Тогда вы бы использовали его в C ++ так:

Person person;
person.set_id(123);
person.set_name("Bob");
person.set_email("bob@example.com");

fstream out("person.pb", ios::out | ios::binary | ios::trunc);
person.SerializeToOstream(&out);
out.close();

Или вот так:

Person person;
fstream in("person.pb", ios::in | ios::binary);
if (!person.ParseFromIstream(&in)) {
  cerr << "Failed to parse person.pb." << endl;
  exit(1);
}

cout << "ID: " << person.id() << endl;
cout << "name: " << person.name() << endl;
if (person.has_email()) {
  cout << "e-mail: " << person.email() << endl;
}

Более полный пример см. В учебниках .

1 голос
/ 17 февраля 2009

Если все, что вам нужно, это пары «ключ-значение», то важная вещь - это типы ключей и значений, которые будут определять цвет ваших действий.

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

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

Если вы предоставите тип ключа / значений, мы можем помочь больше. без этого вот несколько общих советов:

  • Если они поддаются строковому представлению, тогда может быть достаточно простого CSV-файла (но используйте для этого существующую библиотеку читателя-писателя, чтение и запись легального CSV сложнее, чем кажется на первый взгляд)
  • ЕСЛИ они имеют фиксированную ширину, то простой двоичный формат сделает чтение и запись очень легкими (и быстрыми), но следует позаботиться, чтобы признать проблемы:
    • endianess
    • хотите ли вы разрешить простой просмотр таких файлов вместе или добавить CRC-подобные значения для целостности (вы можете сделать и то и другое, но это сложнее)
    • Вы теряете возможность выполнять поиск файлов (это реальная потеря, для этого вам может понадобиться заново изобретать части вашего набора инструментов)
    • нарушит ли формат платформа / компилятор / size_t формат
  • Некоторый структурированный текстовый формат, который легче XML. Существует несколько JSOM / YAML и т. Д. Они обеспечат расширяемость, которая, скорее всего, вам не понадобится.
1 голос
/ 17 февраля 2009

Я не особо хочу сериализовать всю карту, если в этом нет необходимости, так как на самом деле это только содержание, которое я ищу.

Значит ли это, что вам не нужно сериализовать весь объект? Может быть, вам следует пересмотреть только использование текстового формата. Если вам действительно нужно сериализовать только подмножество пар ключ / значение на карте, то вам, вероятно, следует просто записать их в текстовый файл и прочитать их позже. Вам не обязательно нужно XML; должна работать только одна строка на ключ карты, за которой следует одна строка со значением.

...