0

我正在使用 C++ 中的 sstream 对 std::map 进行序列化。序列化功能:

template <class key, class value>
std::string serializeMap(const std::map<key, value>& v){
    std::stringstream ss;
    std::for_each(v.begin(), v.end(), [&ss](const std::pair<key, value>& s){
            ss.write ((char*)&s, sizeof(std::pair<key,value>));
        });
    return ss.str();
}

并使用此反序列化:

template <class key, class value>
void deSerializeMap(const std::string& s, std::map<key, value>& v){

    std::stringstream ss1;

    ss1<<s;

    int pos = 0;
    printf("\nlen %d\n", s.size());
    while(ss1){
        char* ar = new char[sizeof(std::pair<key, value>)];
        ss1.read(ar, sizeof(std::pair<key, value>));
        v.insert(*(reinterpret_cast<std::pair<key, value>*>(ar)));
        pos+=sizeof(std::pair<key, value>);
        ss1.seekg(pos);
        delete[] ar;
    }

}

这可以使用std::string. const char*我必须使用作为参数的 C 函数,我尝试使用c_str()NULL 字符并将其添加到 char 数组,但strlen给出了零。有什么我想念的吗?

4

1 回答 1

1

正如@Nir Friedman 所提到的,如果您正在实现一个序列化程序并且没有在容器的元素上调用它 recursivley,那么您可能做错了什么。

进行这种递归序列化意味着将 POD 类型作为“原子”(递归结束条件),递归步骤是在非 POD 类型的每个成员上调用序列化程序。

一个简单的方法来完成你想要的是通过一个函数模板,如:

template <typename T>
uint64_t write(const T& t);

write 函数通常返回一个无符号整数,表示已序列化的字节数。此模板化函数应专门用于所有 POD 以及您希望序列化的任何非 POD 类型。因此,在您的情况下,除了int, float, double,char等之外,您还需要write(const std::map<K,T>& m)遍历地图并为每个键值对调用write. 同样通常对于序列化,您在实际数据之前写一个标头,以便您可以反序列化数据(例如,您如何知道地图包含多少元素?)。

幸运的是(也许)对你来说,标准库有@Alexander Huszagh 提到的这样一个模式(参见“装饰器”模式),那就是流操作符operator<<(和)序列化 a 的简单方法std::map是:

template<typename K, typename V>
std::ostream& operator<<(std::ostream& os, const std::map<K,V>& m)
{
    os << "map" << '\n';             //write the type
    os << m.size() << '\n'; //write the size of the data
    for(auto&& kvp : m)
    {
        os << "pair" << '\n';
        os << kvp.first << '\n';  //Recursive call here...
        os << kvp.second << '\n'; //Recursive call here...
    }
    return os;
}

上面的反序列化会很复杂,因为递归调用可能只是一个数字、字符或一个字符串(带有新行),它们没有我添加的“标题”,但你的代码似乎假设它知道KeyValue模板参数所以对你来说可能没问题。

无论如何,您不应该尝试自己编写序列化程序,要使其正确和通用是一项艰巨的工作,而且完全浪费时间,因为网络上有很多公开可用的。由于您对序列化地图感兴趣,因此我建议您使用一些 JSON 库。

于 2018-01-06T23:58:18.990 回答