【问题标题】:Reading a string from hdf5 in C++在 C++ 中从 hdf5 读取字符串
【发布时间】:2012-11-28 15:19:06
【问题描述】:

我正在从 Microsoft Visual C++ 2008 中的 H5 文件中读取数据集。对于 int 和 double 类型的数据一切正常,但在遇到字符串时遇到问题。在 H5 文件中,我有 18 个字符串,每个字符串固定长度为 24。我的代码如下;

StrType strdatatype(PredType::C_S1, 24);
char *buffer1[18];
DataSet datasetCurveNames = riskFactorsH5.openDataSet("/gstrCurveNames");

datasetCurveNames.read(&buffer1, strdatatype);

在执行时,缓冲区 1 被错误的指针填充。作为替代方案,我尝试使用 H5T_VARIABLE 通过修改来管理可变长度字符串:

 StrType strdatatype(PredType::C_S1, H5T_VARIABLE);

这也失败了。如果有人能对这个问题有所了解,将不胜感激。

干杯, 卢卡斯

【问题讨论】:

    标签: c++ hdf5


    【解决方案1】:

    HDF5 C++ API 的文档严重不足。这就是我从数据集中读取字符串的方式。我只是在代码完成 IDE 的帮助下才弄清楚这一点:

    using namespace H5;
    std::string field_name("name of the field");
    StrType datatype(0, H5T_VARIABLE);
    DataSpace dataspace(H5S_SCALAR);
    DataSet datset = group.openDataSet(field_name);
    
    std::string field_value;
    datset.read(field_value, datatype, dataspace);
    

    【讨论】:

    • 这是如何工作的? field_value 的内存何时分配?
    • @Walter std::string 类包含自己的内存管理。您可以创建一个 std::string 并为其分配一个 C 字符串。它将调整其内部数组的大小以适当地存储数据。或者你可以直接调用 std::string::resize 来改变内部内存数组的大小并逐个字符分配。有关 std::string 及其内存的更多信息,请参阅 stackoverflow.com/q/9521629/950677
    • 我都知道。我不知道DataSet::read() 分配了一个C 字符串。这从数据类型中显而易见吗? (不适合我)。
    • H5::DataSet::read 的重载将 H5std_string 的引用作为其参数 (hdfgroup.org/HDF5/doc/cpplus_RM/…)。 H5std_string 只是 std::string 周围的 typedef (在大多数系统上;大概有一些特殊情况导致了 H5std_string typedef)。它采用对 std::string 的可变引用(不是 const ref)这一事实意味着它读入了 std::string。如果 API 采用 std::string,那么人们不会期望它需要预先分配
    • 好的,我验证了这在理论上可行。但在实践中它对我不起作用(因为当我使用 5.1 时,我可以使用使用 gcc 4.X 编译的 hdf5 C++ 库,当我使用 std::string 获得对任何东西的未定义引用时,在库中是 @987654327 @ 但在我的代码中 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)。那么,不调用DataSet::read(std::string&, ...)的方法是什么?
    【解决方案2】:

    您需要为完整的字符串分配内存,库不会为您分配内存。你应该替换

    char *buffer1[18];
    

    通过

    char buffer1[18][24];
    

    datasetCurveNames.read(&buffer1, strdatatype);
    

    应该是

    datasetCurveNames.read(buffer1, strdatatype);
    

    (没有&

    【讨论】:

      【解决方案3】:
          auto dataset = file.openDataSet(kDatasetName);
          auto dataspace = dataset.getSpace();
          hsize_t dims_out[2];
          auto ndims = dataspace.getSimpleExtentDims(dims_out, nullptr);
          assert(ndims == 2);
          auto n = dims_out[0] * dims_out[1];
          auto data_type = dataset.getDataType();
          auto type_class = data_type.getClass();
          auto data_size = data_type.getSize();
          void* out = new char[n * data_size]();
          dataset.read(out, data_type);
          if (type_class == H5T_INTEGER) {
          } else if (type_class == H5T_STRING) {
            std::string* strs = new std::string[n];
            for (auto i = 0u; i < n; ++i) {
              auto len = data_size;
              auto c_str = out + data_size * i;
              for (auto p = c_str + len - 1; p != c_str && !*p; --p) --len;
              strs[i].assign(c_str, len);
            }
          }
          free(out);
      

      结帐https://github.com/opentradesolutions/openalpha/blob/hdf5/src/openalpha/data.cc 以获取完整示例

      【讨论】:

        猜你喜欢
        • 2018-05-02
        • 2015-09-29
        • 2017-09-29
        • 2014-06-11
        • 2013-01-03
        • 2019-01-29
        • 2016-06-05
        • 1970-01-01
        • 2014-11-21
        相关资源
        最近更新 更多