隐藏复合数据类型的某些字段,使其不被写入hdf5文件(或从中读回)

时间:2015-10-12 16:13:50

标签: c++ c hdf5

我期待通过不在memory_type中插入字段,我可以避免将该字段输出到磁盘。但是,以下测试程序显示情况并非如此。即使我没有插入字段c,也会写入所有内容并回读所有内容。 (尽管示例代码是用C ++提供的,但使用hdf5的C API的任何解决方案同样受到赞赏!)

#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
#include "H5Cpp.h"
using namespace H5;


const H5std_string FILE_NAME( "test_compound2.hdf5" );
const H5std_string DATASET_NAME( "data" );
const int   LENGTH = 5;
const int   RANK = 1;

#define ShowField(s,f){\
cout << endl<<"Field "<<#f<<" : " << endl; \
  for(int i = 0; i < LENGTH; i++)\
    cout<<s[i].f<<" ";\
      cout<<endl;\
        }

int main(void)
{

  struct s_t
  {
    int    a;
    float  b;
    int c;
    };
  CompType mtype( sizeof(s_t) );
  /*only insert a,b, do not insert c*/
  mtype.insertMember( "a", HOFFSET(s_t, a), PredType::NATIVE_INT);
  mtype.insertMember( "b", HOFFSET(s_t, b), PredType::NATIVE_FLOAT);
  /*note field c is not inserted!*/

  hsize_t dim[] = {LENGTH};
  vector <s_t> datain(LENGTH);
  for(int i=0; i<LENGTH; i++)/* init data*/
  {
    datain[i].a=i;
    datain[i].b=i*i;
    datain[i].c=-i;
    }
  cout<<"==========Data initialized=============\n";
  ShowField(datain, a);
  ShowField(datain, b);
  ShowField(datain, c);

  /*write to file*/
  {
    DataSpace space( RANK, dim );
    H5File file( FILE_NAME, H5F_ACC_TRUNC );
    DataSet dset(file.createDataSet(DATASET_NAME, mtype, space));
    dset.write( datain.data(), mtype );
    }

  /*read back*/
  H5File file( FILE_NAME, H5F_ACC_RDONLY );
  DataSet dset(file.openDataSet( DATASET_NAME ));
  vector <s_t> dataout(LENGTH);

  dset.read( dataout.data(), mtype );

  cout<<"\n===========Data Read==========\n";
  ShowField(dataout,a);
  ShowField(dataout,b);
  ShowField(dataout,c); 

  return 0;
}

输出如下。注意字段c已正确回读,但未插入memtype

  ==========Data initialized=============

  Field a : 
  0 1 2 3 4 

  Field b : 
  0 1 4 9 16 

  Field c : 
  0 -1 -2 -3 -4 

  ===========Data Read==========

  Field a : 
  0 1 2 3 4 

  Field b : 
  0 1 4 9 16 

  Field c : 
  0 -1 -2 -3 -4 

我想这与memtype的大小有关。我尝试使用pack()来减小大小,但数据解释却出错了。

定义仅包含这些所需字段的新结构不是最佳的,因为它需要将数据复制到新结构或返回,而我的应用程序涉及大量数据。我试图隐藏的实际上是一个向量字段,我将其作为可变长度数组的数组单独写出。目前虽然我省略了memtype中的向量字段,但它仍然被写入然后回读,这会破坏内存(读取会自动填充向量的大小和内存指针及其写入的值,这些指针不再是有效的指针)。

那么有没有一种方法可以让我真正隐藏某个特定字段不被编写以及被回读,而无需定义新的临时类?

1 个答案:

答案 0 :(得分:1)

在挖掘文档和测试之后,我找到了以下解决方案。关键是在保存时从内存模型中指定不同的存储模型。此存储类型是mtype的紧凑版本,用于删除未使用的字段。 pack()函数可用于实现此目的:

CompType mtype_disk;
mtype_disk.copy(mtype);
mtype_disk.pack()

现在mtype_disk的大小应该小于mtype,因为删除了未使用的字段(可能还有一些填充)。使用mtype_disk而不是mtype创建数据集将确保只显示明确插入mtype的字段(以及mtype_disk)。

DataSet dset(file.createDataSet(DATASET_NAME, mtype_disk, space));
dset.write(datain.data(), mtype);

数据集创建步骤是唯一需要mtype_disk的地方。回读数据时,应像以前一样使用mtype来描述内存布局。