C ++将std :: map序列化为文件

时间:2011-11-14 12:15:46

标签: c++ serialization stl

我有一个C ++ STL映射,它是int和customType的映射。 customType是一个结构,它包含字符串和字符串列表,如何将其序列化为文件。

示例结构:

struct customType{
string;
string;
int;
list<string>;
}

6 个答案:

答案 0 :(得分:10)

如果您不害怕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); 

答案 1 :(得分:7)

一个简单的解决方案是在一行上输出每个成员,包括列表中的所有字符串。每条记录都以地图的键开头,并以不在列表中的特殊字符或字符序列结束。通过这种方式,您可以一次读取一行,并知道第一行是地图键,第二行是结构中的第一个字符串,依此类推,当您到达特殊记录结束序列时,您知道列表已完成这是地图中下一个项目的时间。此方案使文件生成可读,如果您需要在程序外编辑它们,则可编辑。

答案 2 :(得分:1)

C ++没有Java等反射功能,因此没有“自动”方式。您必须自己完成所有工作:打开文件,在循环中输出每个元素,然后关闭文件。此外,文件没有标准格式,您需要定义一个满足您需求的格式。当然,有些图书馆可以提供帮助,但它们不是语言的一部分。看看这个问题:

Is it possible to automatically serialize a C++ object?

另请看一下: http://s11n.net/

答案 3 :(得分:0)

如果你问这个,那么你可能已经知道你不能通过以下方式序列化这个:

file.write( (const char *) &mapOfCustom, sizeof( mapOfCustom ) );

问题与复杂对象有关(在C ++中,即使是字符串变量也是一个复杂的对象),即那些不是自包含的对象。实际上,即使是简单的序列化也存在问题,从平台兼容性到甚至编译器兼容性(不同的填充等)。

一种方法是使用一个简单的XML库,例如tinyXML:

http://www.grinninglizard.com/tinyxml/

将save保存到XML,并从XML过程中恢复。

答案 4 :(得分:0)

您可以尝试:cxx-prettyprint

答案 5 :(得分:0)

您好,我编写了一个独立的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
}

让我知道这是否有帮助-否则您会发现错误。这是一个非常简单的序列化程序,对我来说真的只是一个学习工具。谷物等较重的方法可能对您更好。