Подтвердить что ты не робот

С++ Сериализация std:: map в файл

У меня есть карта С++ STL, которая представляет собой карту int и customType. CustomType - это структура, которая имеет строку и список строк. Как я могу сериализовать это в файле.

sample struct:

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

Ответ 1

Если вы не боитесь 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); 

Ответ 2

Простым решением является вывод каждого члена в отдельной строке, включая все строки в списке. Каждая запись начинается с ключа к карте и заканчивается специальным символом или символьной последовательностью, которая не может быть в списке. Таким образом, вы можете читать по одной строке за раз, и знать, что первая строка - это ключ карты, вторая строка - первая строка в структуре и т.д., И когда вы достигнете своей особой последовательности окончания записи, вы знаете, что список выполнен и это время для следующего элемента на карте. Эта схема делает файлы сгенерированными читаемыми и редактируемыми, если вам нужно редактировать их вне программы.

Ответ 3

У С++ нет возможностей отражения, таких как Java и другие, поэтому нет "автоматического" способа сделать это. Вам нужно будет выполнить всю работу самостоятельно: откройте файл, выведите каждый элемент в цикле и закройте файл. Также нет стандартного формата для файла, вам нужно будет определить тот, который соответствует вашим потребностям. Конечно, есть библиотеки, чтобы помочь в этом, но они не являются частью языка. Взгляните на этот вопрос:

Можно ли автоматически сериализовать объект С++?

Также взгляните на: http://s11n.net/

Ответ 4

Если вы спрашиваете об этом, то, возможно, вы уже знаете, что вы не можете сериализовать это с помощью:

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

Проблема связана со сложными объектами (и в С++ даже строковая переменная является сложным объектом), то есть те объекты, которые не являются автономными. На самом деле даже простая сериализация имеет проблемы, которые варьируются от платформы совместимы даже до компилятора совместимости (разные прокладки и т.д.).

Один из способов - использовать простую XML-библиотеку, такую ​​как tinyXML:

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

И напишите save в XML и восстановите из XML-процедур.

Ответ 5

Вы можете попробовать следующее: cxx-prettyprint

Ответ 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
}

Дайте мне знать, если это поможет - или вы найдете ошибки. Это довольно простой сериализатор и действительно просто инструмент обучения для меня. Подходы с более тяжелым весом, такие как Cereal, могут работать для вас лучше.