STL 序列化库 (STL-SL)






3.44/5 (15投票s)
STL 序列化库可以对 STL 对象进行序列化并从文件中加载。序列化文件格式可以根据您的需求进行定制。它快速、简单、免费!
快速用户指南
使用 STL 序列化库 (STL-SL) 是一个三步过程。第一步,您使用 STL-SL 声明要序列化的 STL 类型。
value_trait < int > int_filer;
value_trait < std::list< bool > > bool_list_filer;
value_trait < std::map<std::string, std::multimap< float, bool > > > complex_stl_filer;
在代码片段中,声明了三种不同的类型。每种类型都有不同程度的复杂性。int_filer
是所有中最简单的,其中 int
被参数化到 value_trait
模板类中。因此,int_filer
可用于序列化和从序列化文件中加载 int
。
类似地,bool_list_filer
的声明准备好序列化布尔类型列表。而 complex_stl_filer
准备一个 string
和 multimap
数据类型的映射,其中 multimap
存储 float
、bool
对,如上所示。
下一步,创建一个 file_interface
,它需要一个序列化文件名,序列化数据将被写入/读取该文件。
stl_trait_writer file_interface (serialization_filename);
请注意,file_interface
在声明时不需要类型,这意味着不同类型的 STL 对象可能被序列化到同一个序列化文件中。
此外,由于序列化文件接口声明与数据文件声明无关,因此上述两个步骤可以互换位置。
在第三个也是最后一个阶段,数据被序列化到文件或从文件中加载。
filer.serialize ( stl_object, file_interface );
filer.load ( stl_object, file_interface );
以下代码片段说明了上述所有三个步骤的使用情况
//declare serialization-file interfaces
stl_trait_writer file_interface ( ".\\serialization-file.txt");
//declare the STL object
std::vector < int > stl_object;
//declare the data filer
value_trait < std::vector < int > > data_filer;
//...populate data in stl_object...//
//serialize data in stl_object in the file pointed by file_interface
data_filer.serialize ( stl_object, file_interface );
//-- or --//
//load data in the file pointed by file_interface in stl_object STL object
data_filer.load ( stl_object, file_interface );
//...use data in stl_object...//
STL 序列化库
本文介绍了一组模板类,能够以用户定义的格式(默认是文本文件)序列化 STL 对象。
STL 序列化库由两大部分组成:序列化过滤器 (Serialization Filer) 和序列化模板类 (Serialization Template Classes)。
序列化过滤器
它包括以下三个类
//Serialization-file writer class.
//This guy writes the data to the file specified by 'file_path'.
//NOTE: This class does not recognize the data objects containing spaces, tabs,
// new-line characters in them. This may be fixed by overloading '<<' operator and
// adding escape-sequencing logic in it.
class stl_trait_writer: public std::ofstream
{
public:
stl_trait_writer(const std::string& file_path):std::ofstream(file_path.c_str())
{}
};
//Serialization-file reader class.
//This guy reads the data from the file specified by 'file_path'.
//NOTE: This class does not recognize the data objects containing spaces, tabs,
// new-line characters in them. This may be fixed by overloading '>>' operator and
// adding escape-sequencing logic in it.
class file_trait_reader: public std::ifstream
{
public:
file_trait_reader(const std::string& file_path):std::ifstream(file_path.c_str())
{}
};
//Serialization filer class.
//This guy presents the set of reader, writer objects responsible for reading and
// writing to the serialization file.
template <class writer_trait , class reader_trait>
class filer_trait
{
public:
typedef typename writer_trait writer_type;
typedef typename reader_trait reader_type;
};
stl_trait_writer
和 file_trait_reader
类提供了基本的文件 I/O 机制。filer_trait
类是一个过滤器,它只配对上述两种类类型。另一种方法是让 filer_trait
类为了简单性实现文件 I/O 机制,但可能牺牲可伸缩性。
文件写入器类 (stl_trait_writer
) 可以被用户定义的类替换,以将序列化文件格式更改为例如 XML。为从文件中加载序列化数据提供的文件读取器类 (file_trait_writer
) 将需要修改为一个能够理解用户文件格式的类。
序列化模板类
此模块中的类集包含了将复杂的 STL 类型分解为基本类型以及序列化/反序列化基本数据类型的语言机制。
//Basic datatype serializer class.
//Triggers the read or write to the serialization file for the basic datatypes.
//NOTE: This class has been tweaked to work with the 'stl_trait_writer' class.
template <class val_trait, class val_filer_trait =
filer_trait<stl_trait_writer, file_trait_reader> >
class value_trait
{
public:
typedef typename val_filer_trait::writer_type writer_trait;
typedef typename val_filer_trait::reader_type reader_trait;
void serialize(const val_trait& val, writer_trait &pen)
{
pen << val << "\n"; //a tweak for 'stl_trait_writer' class defined above.
//pen << val; //correct code, this should replace above line of code should
//you choose to implement your own 'stl_trait_writer' class.
pen.flush();
}
void load(val_trait& val, reader_trait &pen)
{
pen >> val;
}
};
value_trait
类负责序列化和加载基本数据类型。上面展示的代码被调整为与上一节所述的序列化过滤器类一起使用。
以下摘录说明了将复杂 STL 类型分解为其基本组件的代码
//Sequence-list datatype serializer class.
//Triggers the read or write to the serialization file for the Sequence-list datatypes.
//This class takes care of STL types -- list, vector, stack, queue, deque
// and priority_queue
//NOTE: 'basic_string' type is not treated as sequence-list, but as basic type.
template <class sequence_list_type, class val_filer_trait >
class sequence_list_value_trait
{
public:
typedef typename val_filer_trait::writer_type writer_trait;
typedef typename val_filer_trait::reader_type reader_trait;
typedef typename sequence_list_type::size_type size_type;
typedef typename sequence_list_type::value_type value_type;
void serialize (sequence_list_type& val, writer_trait &pen )
{
value_trait<size_type, val_filer_trait> size_filer;
size_filer.serialize (val.size(), pen);
for(sequence_list_type::iterator i=val.begin(); i != val.end(); i++)
{
value_trait<value_type, val_filer_trait> val_trait_key_filer;
val_trait_key_filer.serialize(*i,pen);
}
}
void load (sequence_list_type& val, reader_trait &pen )
{
value_trait<size_type, val_filer_trait> size_reader;
size_type val_size=0;
size_reader.load(val_size, pen);
for(; val_size > 0; val_size--)
{
value_type element;
value_trait<value_type, val_filer_trait> val_trait_key_reader;
val_trait_key_reader.load(element, pen);
val.push_back(element);
}
}
};
sequence_list_value_trait
类将 list
、vector
、stack
、queue
、deque
和 priority_queue
STL 类型分解为其更小的组件类型。因此,一个 int
类型的 vector
将被分解为 int
类型的一个 list
,该列表由默认的 vector::iterator
类型进行迭代。而 int
类型的值由 value_trait
类进行序列化。
//Triggers the read or write to the serialization file for the Associative-list
// datatypes.
//This class takes care of STL types -- map, multimap, set, multiset
template <class associative_list_type, class val_filer_trait >
class associative_list_value_trait
{
public:
typedef typename val_filer_trait::writer_type writer_trait;
typedef typename val_filer_trait::reader_type reader_trait;
typedef typename associative_list_type::size_type size_type;
typedef typename associative_list_type::key_type key_type;
typedef typename associative_list_type::mapped_type data_type;
void serialize (associative_list_type& val, writer_trait &pen )
{
value_trait<size_type, val_filer_trait> size_filer;
size_filer.serialize (val.size(), pen);
for(associative_list_type::iterator i=val.begin(); i != val.end(); i++)
{
value_trait<key_type, val_filer_trait> val_trait_key_filer;
value_trait<data_type, val_filer_trait> val_trait_data_filer;
val_trait_key_filer.serialize(i->first,pen);
val_trait_data_filer.serialize(i->second,pen);
}
}
void load (associative_list_type& val, reader_trait &pen )
{
value_trait<size_type, val_filer_trait> size_reader;
size_type val_size=0;
size_reader.load(val_size, pen);
for(; val_size > 0; val_size--)
{
key_type key_element;
value_trait<key_type, val_filer_trait> val_trait_key_reader;
val_trait_key_reader.load(key_element, pen);
data_type data_element;
value_trait<data_type, val_filer_trait> val_trait_data_reader;
val_trait_data_reader.load(data_element, pen);
val.insert (std::pair<key_type, data_type> (key_element, data_element));
}
}
};
associative_list_value_trait
类是 sequence_list_value_trait
类的一个复杂版本,其中 map
、multimap
、set
和 multiset
STL 类型被分解为其键和数据元素类型,并根据需要进一步分解或序列化。
以下摘录描绘了复杂 STL 类型如何通过使用上面介绍的 associative_list_value_trait
和 sequence_list_value_trait
类来启动分解过程的机制。
//STL vector datatype serializer class.
//Triggers the read or write to the serialization file for the STL vector datatype.
template <class val_trait_key, class val_trait_data, class val_filer_trait >
class value_trait< std::vector<val_trait_key, val_trait_data> , val_filer_trait >
{
public:
typedef typename val_filer_trait::writer_type writer_trait;
typedef typename val_filer_trait::reader_type reader_trait;
typedef std::vector<val_trait_key, val_trait_data> vector_value_trait;
void serialize (vector_value_trait& val, writer_trait &pen )
{
sequence_list_value_trait<vector_value_trait,
val_filer_trait> sequence_list_value_filer;
sequence_list_value_filer.serialize (val, pen);
}
void load (vector_value_trait& val, reader_trait &pen )
{
sequence_list_value_trait<vector_value_trait,
val_filer_trait> sequence_list_value_reader;
sequence_list_value_reader.load (val, pen);
}
};
以上代码段启动了 vector
STL 类型到更小组件的分解过程,以便进一步序列化。对于 list
、stack
、queue
、deque
和 priority_queue
STL 类型,实现了类似的逻辑。
//STL multimap datatype serializer class.
//Triggers the read or write to the serialization file for the STL multimap datatype .
template <class val_trait_key, class val_trait_data, class val_filer_trait >
class value_trait< std::multimap<val_trait_key, val_trait_data> , val_filer_trait >
{
public:
typedef typename val_filer_trait::writer_type writer_trait;
typedef typename val_filer_trait::reader_type reader_trait;
typedef std::multimap<val_trait_key, val_trait_data> multimap_value_trait;
void serialize (multimap_value_trait& val, writer_trait &pen )
{
associative_list_value_trait<multimap_value_trait,
val_filer_trait> associative_list_value_filer;
associative_list_value_filer.serialize (val, pen);
}
void load (multimap_value_trait& val, reader_trait &pen )
{
associative_list_value_trait<multimap_value_trait,
val_filer_trait> associative_list_value_reader;
associative_list_value_reader.load (val, pen);
}
};
就像上面处理将 vector
类型分解为更小组件的摘录一样,这段代码将 multimap
分解为其键类型和数据类型组件,以便进一步序列化。对于其他关联容器,如 map
、set
和 multiset
,也可以实现类似的逻辑。
注释
需要注意的是,上面提供的库为 STL 过滤器声明中的每个子类型创建了一个类。虽然这不会产生额外的运行时开销,但它使命名空间中被序列化的类的数量加倍。如果类的数量超过了编译器支持的数量,您可能需要重构类层次结构。
上述事实可能被视为一个缺点,但值得注意的是,类的数量不会在运行时产生任何开销。其优点是 STL-SL 代码是类型安全的。
这里呈现的 STL-SL 是第一个修订版;您可能希望在序列化文件中包含被序列化的 STL 类型的类型信息,从而有助于 STL-SL 中的运行时类型检查。
还有其他库,例如 BOOST,它们功能更强大,但可能不那么直观。这些库解决了许多其他问题,如类版本控制、指针恢复和数据可移植性。本文的目的不是取代它们;本文应该被视为一个轻量级、易于使用的替代方案。此外,这里提供的代码可以看作是更完整序列化库实现的一个 STL 序列化引擎。