在 C++ 中从文件存储/读取数据的简单方法

计算科学 C++ 数据管理
2021-12-14 10:08:41

我一直在使用 C++ 运行各种模拟,这样做通常涉及将大量数据保存到文件(实数/复杂矩阵、数组等),然后稍后将它们读入其他程序。但是,我一直无法找到一种一致且简单的方法。我的解决方案通常涉及几十行难以阅读的代码,用于我想从文件中保存/读取的每种不同类型的数据结构。是否有任何已知的库可以做到这一点,或者至少在这个过程中有所帮助?如果有任何类型的矩阵库允许自动保存/读取矩阵/向量到文件,那也会很有帮助(据我所知,Eigen 没有这个选项)。

3个回答

Numpy 有一个非常简单的文件格式,这使得它基本上与所有其他高级语言完美兼容。https://www.numpy.org/devdocs/reference/generated/numpy.lib.format.html)看起来格式比 boost 或 hdf5 轻得多。文档说,如果有必要,自己编写解析器应该很容易,我倾向于相信这一点。粗略的谷歌搜索还表明,在 C++ 中存在许多用于.npy文件的轻量级库(例如https://github.com/rogersce/cnpy)。作为额外的好处,你总是能够在 python 中加载你的文件并在像 ipython 这样的漂亮的 python 解释器中手动检查它们,否则在 C++ 中实现这可能有点棘手。

您可以使用 boost 的序列化工具,它可以直接扩展以支持自定义数据结构。如果您使用 Eigen,您可以调整类似内容以满足您的需求。

Cereal是一个简单易用的 C++ 数据结构序列化库。它了解所有的 STL 数据结构,并且很容易调整自定义类以供使用。

示例代码:

#include <cereal/types/unordered_map.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/archives/binary.hpp>
#include <fstream>

struct MyRecord
{
  uint8_t x, y;
  float z;

  template <class Archive>
  void serialize( Archive & ar )
  {
    ar( x, y, z );
  }
};

struct SomeData
{
  int32_t id;
  std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;

  template <class Archive>
  void save( Archive & ar ) const
  {
    ar( data );
  }

  template <class Archive>
  void load( Archive & ar )
  {
    static int32_t idGen = 0;
    id = idGen++;
    ar( data );
  }
};

int main()
{
  std::ofstream os("out.cereal", std::ios::binary);
  cereal::BinaryOutputArchive archive( os );

  SomeData myData;
  archive( myData );

  return 0;
}