如何用C++将字符串附加到HDF5数据集

How to append a string to HDF5 dataset with C++?

本文关键字:HDF5 数据集 字符串 何用 C++      更新时间:2023-10-16

我想将字符串附加到维度为1的HDF5数据集。以下代码用于将doubles附加到文件test-doubles.h5中的"doubles"数据集,但dataset.write(str, string_type, mspace, fspace)调用中的代码segfault:

#include "H5Cpp.h"
const int RANK = 1;
H5::StrType string_type(H5::PredType::C_S1, H5T_VARIABLE);
void append_double(H5::DataSet &dataset, double value) {
    // dataspace
    hsize_t dims[RANK] = { 1 };
    hsize_t maxdims[RANK] = { H5S_UNLIMITED };
    H5::DataSpace mspace(RANK, dims, maxdims);
    H5::DataSpace space = dataset.getSpace();
    const hsize_t actual_dim = space.getSimpleExtentNpoints();
    // extend the dataset
    hsize_t new_size[RANK];
    new_size[0] = actual_dim + 1;
    dataset.extend(new_size);
    // select hyperslab.
    H5::DataSpace fspace = dataset.getSpace();
    hsize_t offset[RANK] = { actual_dim };
    hsize_t dims1[RANK] = { 1 };
    fspace.selectHyperslab(H5S_SELECT_SET, dims1, offset);
    dataset.write(&value, H5::PredType::NATIVE_DOUBLE, mspace, fspace);
}
void append_string(H5::DataSet &dataset, string value) {
    // dataspace
    hsize_t dims[RANK] = { 1 };
    hsize_t maxdims[RANK] = { H5S_UNLIMITED };
    H5::DataSpace mspace(RANK, dims, maxdims);
    H5::DataSpace space = dataset.getSpace();
    const hsize_t actual_dim = space.getSimpleExtentNpoints();
    // extend the dataset
    hsize_t new_size[RANK];
    new_size[0] = actual_dim + 1;
    dataset.extend(new_size);
    // select hyperslab.
    H5::DataSpace fspace = dataset.getSpace();
    hsize_t offset[RANK] = { actual_dim };
    hsize_t dims1[RANK] = { 1 };
    fspace.selectHyperslab(H5S_SELECT_SET, dims1, offset);
    const char *str = value.c_str();
    dataset.write(str, string_type, mspace, fspace);
}
int main(int argc, char *argv[]) {
    cout << "start" << endl;
    {
        H5::H5File h5_file("test-doubles.h5", H5F_ACC_TRUNC);
        // create data space with unlimited dimensions for doubles
        hsize_t doubles_dims[RANK] = { 0 };
        hsize_t doubles_maxdims[RANK] = { H5S_UNLIMITED };
        H5::DataSpace doubles_fspace(RANK, doubles_dims, doubles_maxdims);
        // enable chunking for this dataset
        H5::DSetCreatPropList cparms;
        hsize_t chunk_dims[RANK] = { 1 };
        cparms.setChunk(RANK, chunk_dims);
        // create dataset for doubles:
        H5::DataSet d_dataset = h5_file.createDataSet("doubles",
        H5::PredType::NATIVE_DOUBLE, doubles_fspace, cparms);
        // append values to this dataset:
        append_double(d_dataset, 1.0);
        append_double(d_dataset, 2.0);
        append_double(d_dataset, 3.0);
        cout << "doubles written." << endl;
    }
    {
        H5::H5File h5_file("test-strings.h5", H5F_ACC_TRUNC);
        // create data space with unlimited dimensions for strings
        hsize_t str_dims[RANK] = { 0 };
        hsize_t str_maxdims[RANK] = { H5S_UNLIMITED };
        H5::DataSpace str_fspace(RANK, str_dims, str_maxdims);
        // enable chunking for this dataset
        H5::DSetCreatPropList str_cparms;
        hsize_t str_chunk_dims[RANK] = { 1 };
        str_cparms.setChunk(RANK, str_chunk_dims);
        // create dataset for doubles:
        H5::DataSet str_dataset = h5_file.createDataSet("strings", string_type, str_fspace, str_cparms);
        // append strings to this dataset:
        append_string(str_dataset, "test1");
        append_string(str_dataset, "test2");
        append_string(str_dataset, "test3");
        cout << "strings written." << endl;
    }
    cout << "all done." << endl;
    return 0;
}

非常感谢你的帮助!

如果更换,一切都会正常工作

dataset.write(str, string_type, mspace, fspace);

带有

dataset.write(&str, string_type, mspace, fspace);

我使用以下内容将字符串写入H5文件:

void writeString(const H5::CommonFG& fg, const string& name, const string& s)
{
    H5::StrType h5stringType(H5::PredType::C_S1, s.length() + 1); // + 1 for trailing zero
    H5::DataSet ds = fg.createDataSet(name, h5stringType, H5::DataSpace(H5S_SCALAR));
    ds.write(s, h5stringType);
    return;
}
int main() {
    H5::H5File file;
    file = H5::H5File(filename, H5F_ACC_EXCL);
    H5::Group group = h5Model.createGroup("/test");
    writeString(group, "string name", "value");
}