【问题标题】:C++ Serializing a std::map to a fileC++ 将 std::map 序列化为文件
【发布时间】:2011-12-28 14:48:11
【问题描述】:

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

示例结构:

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

【问题讨论】:

标签: c++ serialization stl


【解决方案1】:

如果你不怕 BOOST,试试 BOOST 序列化: (模板代码,这里可能有一些错误...)

#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); 

【讨论】:

    【解决方案2】:

    一个简单的解决方案是在一行上单独输出每个成员,包括列表中的所有字符串。每条记录都以映射的键开始,并以不能在列表中的特殊字符或字符序列结束。这样你可以一次读取一行,并且知道第一行是映射键,第二行是结构中的第一个字符串,依此类推,当你到达你的特殊记录结束序列时,你知道列表已经完成现在是地图中下一个项目的时候了。此方案使生成的文件具有可读性,并且如果您需要在程序之外进行编辑,则可以对其进行编辑。

    【讨论】:

      【解决方案3】:

      C++ 不像 Java 和其他那样具有反射功能,因此没有“自动”的方式来做到这一点。您必须自己完成所有工作:打开文件,循环输出每个元素,然后关闭文件。该文件也没有标准格式,您需要定义一种满足您需求的格式。当然,有一些库可以帮助解决这个问题,但它们不是语言的一部分。看看这个问题:

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

      还可以看看: http://s11n.net/

      【讨论】:

        【解决方案4】:

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

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

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

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

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

        并写入保存到 XML,并从 XML 过程中恢复。

        【讨论】:

        • 您还没有完全阅读/理解我的回答。请再仔细点。
        【解决方案5】:

        你可以试试这个:cxx-prettyprint

        【讨论】:

        • 我喜欢这个链接,但不幸的是,这并不能满足 OP 的要求。首先,她的customType 没有实现格式化输出运算符 (&gt;&gt;),更重要的是,序列化通常不是 格式化 输出,而是某种原始的二进制输出。
        • 是的,我确实理解她的要求,但提升序列化或 google protobuf 可能有点过头了。因此我的建议。
        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 2013-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-08
          • 1970-01-01
          相关资源
          最近更新 更多