如何解决序列化地图<fs::path, fs::path>?
我正在使用谷物库将我的类序列化为文件,但遇到了 std::map
的问题 - 特别是使用 std::filesystem::path
的地图。
假设我有一个 Object
类,它只包含一个 map<fs::path,fs::path>
,以及谷物所需的序列化函数:
struct Object
{
map<fs::path,fs::path> _map;
template<class Archive>
void serialize(Archive & archive)
{
archive(_map);
}
friend ostream& operator<<(ostream& outs,const Object c)
{
for (auto const &pair: c._map)
std::cout << "{" << pair.first << ": " << pair.second << "}\n";
return outs;
}
};
在我的主要功能中,我有:
int main()
{
// create Object
cout << "Creating object..." << endl;
Object o;
fs::path a = "bye.txt";
fs::path b = "hello.txt";
o._map[a] = b;
o._map[b] = a;
cout << "Object created: " << endl;
cout << o;
// serialize
cout << "Serializing object...." << endl;
stringstream ss;
cereal::BinaryOutputArchive oarchive(ss);
oarchive(o);
cout << "Object serialized." << endl;
// write to file
cout << "Writing serialized object to file...." << endl;
ofstream file("serialized_object");
file << ss.str();
file.close();
cout << "Object written to file." << endl;
// read from file
cout << "Reading from file..." << endl;
stringstream ss2;
fs::path ins = "serialized_object";
ifstream file_stream(ins,ios::binary);
ss2 << file_stream.rdbuf();
cereal::BinaryInputArchive iarchive(ss2);
Object out;
iarchive(out);
cout << "Object read from file." << endl;
cout << out;
}
在我的输出中,我看到从序列化文件读取时的错误:
Creating object...
Object created:
{"bye.txt": "hello.txt"}
{"hello.txt": "bye.txt"}
Serializing object....
Object serialized.
Writing serialized object to file....
Object written to file.
Reading from file...
terminate called after throwing an instance of 'cereal::Exception'
what(): Failed to read 2573 bytes from input stream! Read 28
我的包括:
#include <iostream>
#include <filesystem>
#include <fstream>
#include <string.h>
#include <map>
#include "cereal/types/map.hpp"
#include "cereal/archives/binary.hpp"
#include "cereal/types/string.hpp"
为了能够序列化fs::path
,我在开头包含了以下代码:
namespace std
{
namespace filesystem
{
template<class Archive>
void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(const Archive&,path& out,const string& in)
{
out = in;
}
template<class Archive>
string CEREAL_SAVE_MINIMAL_FUNCTION_NAME(const Archive& ar,const path& p)
{
return p.string();
}
}
}
我确定我遗漏了一些明显的东西,因为这是我第一次使用麦片。有没有人知道我为什么会遇到这个问题?
解决方法
根据谷物文档,在使用 BinaryArchive 时必须始终使用 ios::binary
标志。以下是他们文档中 this 页面的特定部分:
使用二进制存档和文件流 (std::fstream) 时,请记住在构造流时指定二进制标志 (std::ios::binary)。这可以防止流将您的数据解释为 ASCII 字符并更改它们。
另一个问题是基于 Cereal 如何保证序列化已经完成。根据下面的 link,在尝试读取存档之前,输出存档对象应该超出范围(调用析构函数)。它们使用 RAII 方法,就像 here 所述的 ifstream
和 ofstream
一样。
通过允许 Cereal 库在内部执行写入和读取操作,您可以极大地简化代码。这是您的主要功能的修改版本:
int main()
{
// create Object
cout << "Creating object..." << endl;
Object o;
fs::path a = "bye.txt";
fs::path b = "hello.txt";
o._map[a] = b;
o._map[b] = a;
cout << "Object created: " << endl;
cout << o;
cout << "Serializing object...." << endl;
// scope boundary (a function call would be cleaner)
{
ofstream ofstm("serialized_object",ios::binary);
cereal::BinaryOutputArchive oarchive(ofstm);
// serialize
oarchive(o);
}
cout << "Object serialized and written." << endl;
// deserialize the object by reading from the archive
Object out;
// scope boundary (a function would be cleaner)
{
ifstream istm("serialized_object",ios::binary);
cereal::BinaryInputArchive iarchive(istm);
//deserialize
iarchive(out);
}
cout << "Object read from file." << endl;
cout << out;
}
我希望这会有所帮助。请在使用前全部测试。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。