Serialization with boost

Boost имеет множество полезных библиотек. И хотя многие возражают против использования его в серъезных коммерческих проектах, но тяжело переоценить удобство использования библиотек boost.

В процессе работы возникла задача сериализации данных некой структуры с последующим сохранением их в файл. ИМХО, для таких задач просто отлично подходит boost::serialization.

Ниже будут некоторые примеры работы с данной библиотекой. Более детально можно ознакомиться с ней на boost.org(boost::serialization)

Приступим. Есть структура.

struct SomeData
{
std::string dataName;
std::string dataOwner;
uint32 dataSize;
}

Чтобы сериализовать данные, используя boost нам необходимо сделать в ней несколько дополнительных
объявлений.
Во-первых, структура должна быть friend class boost::serialization::access.
А во-вторых, она должна иметь метод serialize

// When the class Archive corresponds to an output archive, the
// & operator is defined similar to <<.  Likewise, when the class Archive
// is a type of input archive the & operator is defined similar to >>.
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & smthing;
}

Итого результат:

struct SomeData
{
friend class boost::serialization::access;std::string dataName;
std::string dataOwner;
uint32 dataSize;template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & dataName;
ar & dataOwner;
ar & dataSize;
}
}

Посмотрим как это все работает
Для использования boost::serialization в проекте нам необходимо подключить(так говорит пример). 

#include <boost/archive/tmpdir.hpp>#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>#include <boost/serialization/base_object.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/assume_abstract.hpp> 

Для того, чтобы сохранить данные в файл нам необходимо написать 3 строчки:

// Structure to serializationSomeData data;
data.dataName = "simple data";
data.dataOwner = "Bill";
data.dataSize = 100;// Create data file
std::ofstream resultFile("dataFile.bin");
boost::archive::text_oarchive oa(resultFile);
oa << data; 

По итогу получаем файл со следующими данными

22 serialization::archive 5 0 0 11 simple data 4 Bill 100

Не очень читабельно, особенно для больших объемов информации. Поэтому есть возможность легко
сохранить данные в *.xml файл. Для этого импользуем макрос BOOST_SERIALIZATION_NVP.
Во-первых, добавляем еще один include:

#include <boost/archive/xml_oarchive.hpp>

Во-вторых, изменится наша структура:

struct SomeData
{
friend class boost::serialization::access;std::string dataName;
std::string dataOwner;
uint32 dataSize;template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(dataName);
ar & BOOST_SERIALIZATION_NVP(dataOwner);
ar & BOOST_SERIALIZATION_NVP(dataSize);
}
} 

Во-вторых еще раз, используем не text_oarchive, а xml_oarchive.

boost::archive::text_oarchive oa(resultFile);
oa << BOOST_SERIALIZATION_NVP(data);

Результатом работы такого кода будет:

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes” ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature=”serialization::archive” version=”5″>
<data class_id=”0″ tracking_level=”0″ version=”0″>
<dataName>simple data</dataName>
<dataOwner>Bill</dataOwner>
<dataSize>100</dataSize>
</data>
</boost_serialization>

Чтобы вычитать данные из файла делаем обратные действия:

std::ifstream inFile("dataFile.xml");
boost::archive::xml_iarchive ia(inFile);
ia &gt;&gt; BOOST_SERIALIZATION_NVP(data);

Также boost поддерживает некоторые из стандартных контейнеров, хотя для массивов(векторов) приходится сериализовать каждый элемент.

Leave a comment