XxY*_*ixX -3 c++ python io file readfile
我创建了一个 Python 脚本,它创建了以下地图(插图):
map<uint32_t, string> tempMap = {{2,"xx"}, {200, "yy"}};
Run Code Online (Sandbox Code Playgroud)
并将其保存为map.out文件(二进制文件)。当我尝试从 C++ 读取二进制文件时,它不会复制地图,为什么?
map<uint32_t, string> tempMap;
ifstream readFile;
std::streamsize length;
readFile.open("somePath\\map.out", ios::binary | ios::in);
if (readFile)
{
readFile.ignore( std::numeric_limits<std::streamsize>::max() );
length = readFile.gcount();
readFile.clear(); // Since ignore will have set eof.
readFile.seekg( 0, std::ios_base::beg );
readFile.read((char *)&tempMap,length);
for(auto &it: tempMap)
{
/* cout<<("%u, %s",it.first, it.second.c_str()); ->Prints map*/
}
}
readFile.close();
readFile.clear();
Run Code Online (Sandbox Code Playgroud)
不可能读取原始字节并让它构造一个(或大多数容器,就此而言)[ 1];因此您将不得不编写一些代码来执行正确的序列化。map
如果存储/加载的数据很简单,按照您的示例,那么您可以轻松地设计一个方案来序列化它,然后编写代码来加载它。例如,可以通过在换行符后写入每个成员的文件来建立简单的明文映射:
<number>
<string>
...
Run Code Online (Sandbox Code Playgroud)
所以对于你的例子:
<number>
<string>
...
Run Code Online (Sandbox Code Playgroud)
这可以编码为:
std::map<std::uint32_t, std::string> tempMap = {{2,"xx"}, {200, "yy"}};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,反序列化的代码将简单地逐一读取每个值并重建map:
2
xx
200
yy
Run Code Online (Sandbox Code Playgroud)
注意:为此,您需要 Python 程序输出将从 C++ 程序中读取的格式。
如果您尝试读/写的数据足够复杂,您可以考虑不同的序列化交换格式。由于您在 python 和 C++ 之间工作,因此您需要研究支持两者的库。有关建议列表,请参阅跨平台和语言(反)序列化的答案
[1]
您不能仅以字节形式读取(或写入)整个容器并使其工作的原因是因为容器中的数据不是内联存储的。写出原始字节不会2 xx\n200 yy\n自动为您产生类似的结果。相反,您将写入指向间接数据结构(例如映射的内部节点对象)的指针的原始地址。
例如,假设的map实现可能包含如下节点:
// Note: untested
auto loadMap(const std::filesystem::path& path) -> std::map<std::uint32_t, std::string>
{
auto result = std::map<std::uint32_t, std::string>{};
auto file = std::ifstream{path};
while (true) {
auto key = std::uint32_t{};
auto value = std::string{};
if (!(file >> key)) { break; }
if (!std::getline(file, value)) { break; }
result[key] = std::move(value);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
(真正的map实现比这复杂得多,但这是一个简化的表示)
如果map<Key,Value>包含一个map_node<Key,Value>成员,那么以二进制形式写出该成员将写入 、 、 和 的二进制表示形式key-value后者left是right指针。对于任何使用任何类型间接的容器也是如此。地址在写入和读取时会有根本的不同,因为它们取决于程序在任何给定时间的状态。
您可以编写一个简单的代码map_node来测试它,然后打印出字节来查看它会产生什么;指针也将被序列化。map从行为上来说,这与您尝试对二进制文件执行的操作完全相同。请参阅下面的示例,其中包含不同的地址。