Чтение строки из hdf5 в C ++

Я читаю наборы данных из файла H5 в Microsoft Visual C ++ 2008. Все работает нормально для данных типа int и double, но я сталкиваюсь с проблемами, когда сталкиваюсь со строками. В файле H5 у меня 18 строк фиксированной длины 24. Мой код выглядит следующим образом;

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

datasetCurveNames.read(&buffer1, strdatatype);

При выполнении buffer1 заполняется неверными указателями. В качестве альтернативы я попытался использовать H5T_VARIABLE для управления строками переменной длины с модификацией:

 StrType strdatatype(PredType::C_S1, H5T_VARIABLE);

Это тоже не удается. Если кто-то может пролить свет на этот вопрос, мы будем очень признательны.

Привет, Лукас


person user1893603    schedule 11.12.2012    source источник


Ответы (3)


API HDF5 C ++ крайне недостаточно документирован. Вот как я читаю строки из набора данных. Я понял это только с помощью 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);
person Nathan    schedule 26.05.2014
comment
Как это работает? когда выделяется память для field_value? - person Walter; 02.07.2015
comment
@Walter Класс std :: string содержит собственное управление памятью. Вы можете создать std :: string и просто присвоить ему C-строку. Он изменит размер своего внутреннего массива для надлежащего хранения данных. Или вы можете вызвать std :: string :: resize напрямую, чтобы изменить размер массива внутренней памяти и назначить его посимвольно. См. stackoverflow.com/q/9521629/950677 для получения дополнительной информации о std :: string и его памяти. - person Nathan; 02.07.2015
comment
Я все это знаю. Чего я не знал, так это того, что DataSet::read() присваивает C-строку. Это очевидно из типа данных? (не для меня). - person Walter; 02.07.2015
comment
Имеется перегрузка H5 :: DataSet :: read, которая принимает в качестве аргумента ссылку на H5std_string (hdfgroup.org/HDF5/doc/cpplus_RM/). H5std_string - это просто определение типа вокруг std :: string (в большинстве систем; по-видимому, есть особые случаи, которые привели к определению типа H5std_string). Тот факт, что он принимает изменяемую ссылку на std :: string (а не на const ref), означает, что он считывается в std :: string. Если API принимает std :: string, то нельзя ожидать, что он потребует предварительного выделения. - person Nathan; 06.07.2015
comment
Хорошо, я убедился, что это сработало ... теоретически. Но на практике это не сработает для меня (потому что библиотека hdf5 C ++, которую я могу использовать, была скомпилирована с gcc 4.X, в то время как я использую 5.1, когда я получаю неопределенные ссылки на что-либо, использующее std::string, что в библиотеке std::basic_string<char, std::char_traits<char>, std::allocator<char> >, но в моем код std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >). Итак, как это сделать без вызова DataSet::read(std::string&, ...)? - person Walter; 06.07.2015
comment
@Walter Если у вас возникли подобные проблемы, я бы либо переключил компиляторы, либо нашел / сделал другую сборку HDF5, либо вообще отказался от интерфейса C ++ и использовал интерфейс C. См. hdfgroup .org / ftp / HDF5 / examples / examples-by-api / hdf5-examples / для примера чтения строки с использованием интерфейса C. Вы также можете посмотреть void H5::DataSet::read( H5std_string& strg, ...) в hdfgroup.org / ftp / HDF5 / current / src / unpacked / c ++ / src / (это просто тонкая обертка вокруг интерфейса C) - person Nathan; 06.07.2015
comment
спасибо за ваши мысли. Теперь я лучше понимаю проблему (прочитав это). - person Walter; 07.07.2015
comment
@Walter Я понятия не имел, что ABI g ++ 5.1 изменился. Это отличная информация! - person Nathan; 07.07.2015
comment
Хорошая находка. H5T_VARIABLE и связанные с ним концепции задокументированы в Руководство пользователя HDF5 - person Johannes Luong; 25.10.2016

Вам нужно выделить память для полных строк, библиотека не сделает этого за вас. Вам следует заменить

char *buffer1[18];

by

char buffer1[18][24];

а также

datasetCurveNames.read(&buffer1, strdatatype);

должно быть

datasetCurveNames.read(buffer1, strdatatype);

(no &)

person Simon    schedule 12.12.2012

    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 для полного примера.

person poordeveloper    schedule 10.01.2019