Zach G
Zach G

Reputation: 29

HDF5 Simple Read of Dataset Fails

I am looking to do a simple read from an hdf5 file using C++. I will split this up into 4 parts. 1st what the file looks like. 2nd my code which attempts to read the file. 3rd the error message. 4th my conclusions.

1.The File - The dataset can be found in the file as shown:

$ h5ls -r myfile.h5
/                     Group
/mydata               Dataset {1200}

Note - The dataset is an array of 1200 strings. Note the CTYPE is H5T_C_S1 which is what I will use to read it in.

HDF5 "myfile.h5" {
GROUP "/" {
   DATASET "mydata" {
      DATATYPE  H5T_STRING {
         STRSIZE H5T_VARIABLE;
         STRPAD H5T_STR_NULLTERM;
         CSET H5T_CSET_UTF8;
         CTYPE H5T_C_S1;
      }
      DATASPACE  SIMPLE { ( 1200 ) / ( 1200 ) }
      DATA {
      (0): "pxsntpfcnkeesswwpwopksu", "exsytafcbkecsswwpwopnng",
      (2): "ebswtlfcbnecsswwpwopnnm", "pxywtpfcnneesswwpwopksu",
      (4): "exsgfnfwbktesswwpwoenag", "exyytafcbnecsswwpwopkng",

2.The Code - My code attempts to read the dataset like so:

#include "H5Cpp.h"
#ifndef H5_NO_NAMESPACE
    using namespace H5;
#endif

const H5std_string FILE_NAME("myfile.h5");
const H5std_string DATASET_NAME("mydata");

// open file
H5File file(FILE_NAME, H5F_ACC_RDONLY);

// get dataset
DataSet dataset = file.openDataSet(DATASET_NAME);

// get src dataspace
DataSpace src = dataset.getSpace();

// get dimensions
int NUM_DIMS = src.getSimpleExtentNdims();
std::vector<hsize_t> dims(NUM_DIMS);
src.getSimpleExtentDims(&dims[0]);
hsize_t height = dims[0];
hsize_t width = 23;

// define src hyperslab
std::vector<hsize_t> count(NUM_DIMS, 1);
std::vector<hsize_t> offset(NUM_DIMS, 0);
src.selectHyperslab(H5S_SELECT_SET, &count[0], &offset[0]);

// define dst hyperslab
DataSpace dst(NUM_DIMS, dims);
dst.selectHyperslab(H5S_SELECT_SET, &count[0], &offset[0]);

// read data into memory, array of cstrings
std::vector<char*> data_out(height);
dataset.read(&data_out[0], H5T_C_S1, dst, src);

// print first line
std::cout << data_out[0] << std::endl;

3.The Error - However, it fails from what appears to be a type mismatch between the src and dst hyperslabs, even though I designed the src and dst to have the same dimensions. The error message is as follows:

HDF5-DIAG: Error detected in HDF5 (1.10.3) thread 0:
  #000: H5Dio.c line 199 in H5Dread(): can't read data
    major: Dataset
    minor: Read failed
  #001: H5Dio.c line 467 in H5D__read(): unable to set up type info
    major: Dataset
    minor: Unable to initialize object
  #002: H5Dio.c line 993 in H5D__typeinfo_init(): unable to convert between src and dest datatype
    major: Dataset
    minor: Feature is unsupported
  #003: H5T.c line 4546 in H5T_path_find(): can't find datatype conversion path
    major: Datatype
    minor: Can't get value
  #004: H5T.c line 4762 in H5T__path_find_real(): no appropriate function for conversion path
    major: Datatype
    minor: Unable to initialize object
HDF5-DIAG: Error detected in HDF5 (1.10.3) thread 0:
  #000: H5T.c line 1756 in H5Tclose(): immutable datatype
    major: Invalid arguments to routine
    minor: Bad value
DataType::~DataType - H5Tclose failed

4.My Conclusions - I have attempted many variations, including removing dst and src as parameters for dataset.read(), changing H5T_C_S1 to PredType::C_S1 and PredType::NATIVE_CHAR, however the same error persists.

How do I simply read the dataset into memory? Is the datatype truly mismatched or is there something else I am not defining? Am I still using the wrong datatype in the read function? Am I defining my hyperslabs improperly such that there actually is a type mismatch?

Upvotes: 0

Views: 1837

Answers (1)

SOG
SOG

Reputation: 912

Maybe you want to try out HDFql and abstract yourself from HDF5 low-level details. In C++ using HDFql, you could read your variable-length char dataset mydata (contained in file myfile.h5) like this:

HDFql::execute("SELECT FROM myfile.h5 mydata"); // select (i.e. read) dataset "mydata" from file "myfile.h5" and populate default cursor with it

while(HDFql::cursorNext() == HDFql::Success) // display content of default cursor
{
    std::cout << HDFql::cursorGetChar() << std::endl;
}

Upvotes: 1

Related Questions