如何将浮点数的 2D std 向量写入 HDF5 文件,然后在 python 中读取它

How to write 2D std vector of floats to HDF5 file and then read it in python

我想将浮点数的二维向量写入 HDF5 文件。 我使用了以下代码 (writeh5.cpp):

#include <cstdlib> 
#include <ctime> 
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <H5Cpp.h>

using namespace H5;
using namespace std;

int main(void) {
  int nrow = 5;
  int ncol = 4;

  vector<vector< double > > vec2d;
  vec2d.resize(nrow, vector<double>(ncol, 0.0));

  srand((unsigned)time(0));

  typename vector< vector< double > >::iterator row;
  typename vector< double >::iterator col;
  for (row = vec2d.begin(); row != vec2d.end(); row++) {
    cout << endl;
    for (col = row->begin(); col != row->end(); col++) {

      *col = (rand()/(RAND_MAX+1.0));
      cout << *col << '\t';
    }
  }
  cout << endl;

  H5File file("test.h5", H5F_ACC_TRUNC);

  // dataset dimensions
  hsize_t dimsf[2];
  dimsf[0] = nrow;
  dimsf[1] = ncol;
  DataSpace dataspace(2, dimsf);

  DataType datatype(H5::PredType::NATIVE_DOUBLE);
  DataSet dataset = file.createDataSet("data", datatype, dataspace);

  // dataset.write(vec2d.data(), H5::PredType::NATIVE_DOUBLE);
  dataset.write(&vec2d[0][0], H5::PredType::NATIVE_DOUBLE);

  cout << endl << " vec2d has " << endl;
  for (row = vec2d.begin(); row != vec2d.end(); row++) {
      cout << endl;
      for (col = row->begin(); col != row->end(); col++) {            

        cout << *col << '\t';
      }
  }
  cout << endl;

  dataset.close();
  dataspace.close();
  file.close();

  return 0;
}

我用g++ writeh5.cpp -I/usr/include/hdf5/ -lhdf5_cpp -lhdf5 -Wall

编译的

A 运行 代码产生以下输出:

0.325553        0.598941        0.364489        0.0125061
0.374205        0.0319419       0.380329        0.815621
0.863754        0.386279        0.0173515       0.15448
0.703936        0.372486        0.728436        0.991631
0.666207        0.568983        0.807475        0.964276

和文件 test.h5

然后当我从 python 读取此文件时(使用以下内容)

import h5py
import numpy as np

file = h5py.File("test.h5", 'r')
dataset = np.array(file["data"])

print dataset

file.close()

我得到了

 [[  3.25553381e-001   5.98941262e-001   3.64488814e-001   1.25061036e-002]
 [  0.00000000e+000   2.42092166e-322   3.74204732e-001   3.19418786e-002]
 [  3.80329057e-001   8.15620518e-001   0.00000000e+000   2.42092166e-322]
 [  8.63753530e-001   3.86278684e-001   1.73514970e-002   1.54479635e-001]
 [  0.00000000e+000   2.42092166e-322   7.03935940e-001   3.72486182e-001]]

第一行不错,其他行都是垃圾。

我试过 dataset.write(&vec2d[0]...dataset.write(vec2d[0].data()...,我遇到了类似的问题。

我要

  1. 用 2D std::vector 双精度的内容写一个 HDF5 文件,
  2. 读取python中的文件并将内容存储在一个numpy数组中

我做错了什么?

这是什么?

gives

0.325553        0.598941        0.364489        0.0125061
0.374205        0.0319419       0.380329        0.815621
0.863754        0.386279        0.0173515       0.15448
0.703936        0.372486        0.728436        0.991631
0.666207        0.568983        0.807475        0.964276

我没有看到打印您的 C++ 代码。您是否使用其他工具读取了该文件?

(是的,这是一个澄清问题,但它需要太多的格式来适应评论)。


使用 Visual C++ 将二维数组 int[n][m] 写入 HDF5 文件

解说写a vector of vectors。它还讨论了编写可变长度数组。

您可能必须在数据集中写入一行迭代器

for (row = vec2d.begin(); row != vec2d.end(); row++) {
      dataset.write(*row, H5::PredType::NATIVE_DOUBLE);
      # or dataset.write(row[0], ...)?
      }
  }

显然,我不允许将 std::vector 向量传递给写入函数。因此,将向量的元素复制到静态数组就解决了这个问题,因为写入函数很乐意接受这个数组。

但是,我对这个解决方案不满意,我希望使用向量 直接进入write函数。

代码如下:

#include <cstdlib> 
#include <ctime> 
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <H5Cpp.h>

using namespace H5;
using namespace std;

int main(void) {
  int nrow = 5;
  int ncol = 4;

  vector<vector< double > > vec2d;
  vec2d.resize(nrow, vector<double>(ncol, 0.0));

  srand((unsigned)time(0));

  // generate some data
  typename vector< vector< double > >::iterator row;
  typename vector< double >::iterator col;
  for (row = vec2d.begin(); row != vec2d.end(); row++) {
    cout << endl;
    for (col = row->begin(); col != row->end(); col++) {            
        *col = (rand()/(RAND_MAX+1.0));
        cout << *col << '\t';
    }
  }
  cout << endl;

  double varray[nrow][ncol];
  for( int i = 0; i<nrow; ++i) {
    cout << endl;
    for( int j = 0; j<ncol; ++j) {
        varray[i][j] = vec2d[i][j];
    }
  }

  H5File file("test.h5", H5F_ACC_TRUNC);

  // dataset dimensions
  hsize_t dimsf[2];
  dimsf[0] = nrow;
  dimsf[1] = ncol;
  DataSpace dataspace(2, dimsf);

  DataType datatype(H5::PredType::NATIVE_DOUBLE);
  DataSet dataset = file.createDataSet("data", datatype, dataspace);

  dataset.write(varray, H5::PredType::NATIVE_DOUBLE);


  cout << endl;

 dataset.close();
 dataspace.close();
 file.close();
 return 0;
}

我 运行 在将数据从矢量转换为动态二维数组时遇到了同样的问题。 h5write 命令的问题不在于它不接受向量,它不理解指针数组的概念。它只写出连续的内存。向量的向量在内存中不是连续的,而是指向一堆向量的指针数组。这就是为什么当您传递数组的第一个元素时,第一行是正确的。 table 的其余部分只是第一个向量之后内存中的垃圾。

我的解决方案是创建一个巨大的一维向量并执行我自己的索引来来回转换。这类似于 h5_writedyn.c https://www.hdfgroup.org/ftp/HDF5/examples/misc-examples/h5_writedyn.c

中的方法