C ++读取在Python中创建的二进制文件中的地图

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)

Hum*_*ler 5

不可能读取原始字节并让它构造一个(或大多数容器,就此而言)[ 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后者leftright指针。对于任何使用任何类型间接的容器也是如此。地址在写入和读取时会有根本的不同,因为它们取决于程序在任何给定时间的状态。

您可以编写一个简单的代码map_node来测试它,然后打印出字节来查看它会产生什么;指针也将被序列化。map从行为上来说,这与您尝试对二进制文件执行的操作完全相同。请参阅下面的示例,其中包含不同的地址。

Live Example