将std::map序列化为文件
C++ Serializing a std::map to a file
我有一个c++ STL映射,它是int和customType的映射。customType是一个结构体,它有字符串和字符串列表,我如何将其序列化到一个文件。
样本结构:struct customType{
string;
string;
int;
list<string>;
}
如果你不怕BOOST,试试BOOST Serialize:(模板代码,这里可能有一些错误…)
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/list.hpp>
struct customType{
string string1;
string string2;
int i;
list<string> list;
// boost serialize
private:
friend class boost::serialization::access;
template <typename Archive> void serialize(Archive &ar, const unsigned int version) {
ar & string1;
ar & string2;
ar & i;
ar & list;
}
};
template <typename ClassTo>
int Save(const string fname, const ClassTo &c)
{
ofstream f(fname.c_str(), ios::binary);
if (f.fail()) return -1;
boost::archive::binary_oarchive oa(f);
oa << c;
return 0;
}
用法:
Save< map<int, customType> >("test.map", yourMap);
一个简单的解决方案是在一行中单独输出每个成员,包括列表中的所有字符串。每个记录以映射的键开始,并以不能在列表中出现的特殊字符或字符序列结束。通过这种方式,您可以一次读取一行,并且知道第一行是映射键,第二行是结构中的第一个字符串,以此类推,当您到达特殊的记录结束序列时,您知道列表已经完成,是时候读取映射中的下一个项了。该方案使生成的文件可读,如果需要在程序外编辑它们,则可编辑。
c++没有像Java和其他语言那样的反射功能,所以没有"自动"的方法来做到这一点。您必须自己完成所有的工作:打开文件,在循环中输出每个元素,然后关闭文件。此外,该文件没有标准格式,您需要定义一种满足您需要的格式。当然,有一些库可以提供帮助,但它们不是语言的一部分。看一下这个问题:
是否可以自动序列化一个c++对象?
还可以看看:http://s11n.net/
如果你问这个问题,那么你可能已经知道你不能通过:
来序列化它。file.write( (const char *) &mapOfCustom, sizeof( mapOfCustom ) );
这个问题与复杂对象有关(在c++中,甚至一个字符串变量也是一个复杂对象),也就是说,那些不是自包含的对象。实际上,即使是简单的序列化也有问题,从平台兼容性到编译器兼容性(不同的填充等)。
一种方法是使用简单的XML库,如tinyXML: http://www.grinninglizard.com/tinyxml/并写入保存到XML,并从XML过程中恢复。
你可以试试:cxx-prettyprint
嗨,我写了一个独立的C11头来实现这一点。你的例子一个自定义类的映射,我只是添加-以确保它工作8)
https://github.com/goblinhack/simple-c-plus-plus-serializer#include "c_plus_plus_serializer.h"
class Custom {
public:
int a;
std::string b;
std::vector c;
friend std::ostream& operator<<(std::ostream &out,
Bits my)
{
out << bits(my.t.a) << bits(my.t.b) << bits(my.t.c);
return (out);
}
friend std::istream& operator>>(std::istream &in,
Bits my)
{
in >> bits(my.t.a) >> bits(my.t.b) >> bits(my.t.c);
return (in);
}
friend std::ostream& operator<<(std::ostream &out,
class Custom &my)
{
out << "a:" << my.a << " b:" << my.b;
out << " c:[" << my.c.size() << " elems]:";
for (auto v : my.c) {
out << v << " ";
}
out << std::endl;
return (out);
}
};
static void save_map_key_string_value_custom (const std::string filename)
{
std::cout << "save to " << filename << std::endl;
std::ofstream out(filename, std::ios::binary );
std::map< std::string, class Custom > m;
auto c1 = Custom();
c1.a = 1;
c1.b = "hello";
std::initializer_list L1 = {"vec-elem1", "vec-elem2"};
std::vector l1(L1);
c1.c = l1;
auto c2 = Custom();
c2.a = 2;
c2.b = "there";
std::initializer_list L2 = {"vec-elem3", "vec-elem4"};
std::vector l2(L2);
c2.c = l2;
m.insert(std::make_pair(std::string("key1"), c1));
m.insert(std::make_pair(std::string("key2"), c2));
out << bits(m);
}
static void load_map_key_string_value_custom (const std::string filename)
{
std::cout << "read from " << filename << std::endl;
std::ifstream in(filename);
std::map< std::string, class Custom > m;
in >> bits(m);
std::cout << std::endl;
std::cout << "m = " << m.size() << " list-elems { " << std::endl;
for (auto i : m) {
std::cout << " [" << i.first << "] = " << i.second;
}
std::cout << "}" << std::endl;
}
void map_custom_class_example (void)
{
std::cout << "map key string, value class" << std::endl;
std::cout << "============================" << std::endl;
save_map_key_string_value_custom(std::string("map_of_custom_class.bin"));
load_map_key_string_value_custom(std::string("map_of_custom_class.bin"));
std::cout << std::endl;
}
输出:map key string, value class
============================
save to map_of_custom_class.bin
read from map_of_custom_class.bin
m = 2 list-elems {
[key1] = a:1 b:hello c:[2 elems]:vec-elem1 vec-elem2
[key2] = a:2 b:there c:[2 elems]:vec-elem3 vec-elem4
}
让我知道这是否有帮助-或者你发现了错误。它是一个非常简单的序列化器,对我来说只是一个学习工具。
- 从一个文件中读取多个序列化对象
- 如何在C++中从头开始反序列化文件(没有库)
- 如何使用自定义对象的序列化在 c++ 中编写自定义二进制文件处理程序
- 如何减少序列化当前所需的样板文件
- 在Qt C++中序列化/解析一个文件中的多个对象
- 使用提升序列化读取具有批大小的二进制文件
- 提升序列化在从二进制文件读取时引发异常
- 从提升序列化文件读取会引发异常
- (De/)序列化作为C++中基于文件的数据交换的接口
- 在没有序列化库的情况下,在 c++ 中从结构体读取和写入文件的最简单方法是什么?
- C++:使用Boost序列化来写入/读取文件
- 如何反序列化包含多个记录的文件
- 如何通过从文件中读取来反序列化C++的字节数组
- C/C++:如何使用制表从文本文件中读取序列化图形(树)
- 序列化与文件加载
- c++增强序列化如何防止不正确的文件崩溃
- Boost序列化和文件IO非常慢
- 反序列化Google Protobuf二进制文件
- 文件夹路径序列化的最大字符长度
- 提升序列化在特定文件大小后抛出"input stream error"