HDF5属性:字符串只有一个字符长

时间:2014-05-15 18:55:30

标签: c string hdf5

我正在编写代码来生成HDF,而且我遇到了属性问题。这些属性都是可变长度的字符串,从文本文件中读取,但我非常慷慨地限制它们为256个字符。

我的代码编译并运行没有错误。当我在HDFView中打开文件时,属性都具有正确的名称,但只显示字符串中的第一个字符。

我已经开始编写接受属性作为单个字符串或字符串数​​组的代码。我还没有完成那部分,所以现在它对字符串数组没有做任何事情。

这是输入文件:

year 2013
julian_date 23
start_time_utc 13:54:03
end_time_utc 14:32:05
pixels_per_degree 1000
latitude_corners 34.988644 35.503284 35.960529 36.364529
longitude_corners -119.571877 -118.467979 -120.158424 -119.004395

以下是代码段:

#define FIELDSTRINGLENGTH 256

/*...*/

while(fgets(line, ATTRSTRINGLENGTH, topattributefile)!=NULL) {
  //parse line into individual words                                                                                                                                         
  field=strtok(line," \n");
  strncpy(attributename, field, FIELDSTRINGLENGTH);
  numfields=0;
  field=strtok(NULL," \n");
  while(field!=NULL) {
    strncpy(attributevalue[numfields++], field, FIELDSTRINGLENGTH);
    field=strtok(NULL," \n");
  }
  if(numfields==0) {printf("ERROR: Attribute %s had no value; skipping\n", attributename);}
  else if(numfields>1) {
    if(verboseflag) {printf("Making array of %d attributes with name %s:\n",
                            numfields, attributename);}
    for(i=0;i<numfields;i++) {
      if(verboseflag) {printf("\t%d: %s\n", i, attributevalue[i]);}
    }
  }
  else {
    printf("Making single attribute: %s: %s\n",
                            attributename, attributevalue[0]);}
    //make single attribute                                                                                                                                                  
    attrdataspaceid = H5Screate(H5S_SCALAR);
    attrdatatypeid = H5Tcopy(H5T_C_S1);
    status = H5Tset_size(attrdatatypeid, FIELDSTRINGLENGTH);
    status = H5Tset_strpad(attrdatatypeid, H5T_STR_NULLTERM);
    attributeid = H5Acreate2(fileid, attributename, attrdatatypeid, attrdataspaceid, H5P_DEFAULT, H5P_DEFAULT);
    status = H5Awrite(attributeid, H5T_C_S1, attributevalue[0]);
  }
}

以下是相关代码段的标准输出:

Making top level attributes...
Making single attribute: year: 2013
Making single attribute: julian_date: 23
Making single attribute: start_time_utc: 13:54:03
Making single attribute: end_time_utc: 14:32:05
Making single attribute: pixels_per_degree: 1000
Making array of 4 attributes with name latitude_corners:
    0: 34.988644
    1: 35.503284
    2: 35.960529
    3: 36.364529
Making array of 4 attributes with name longitude_corners:
    0: -119.571877
    1: -118.467979
    2: -120.158424
    3: -119.004395
Finished making top level attributes.

最后,这是在HDFView中读取的HDF的元数据。

XXXX.XXXXXX.XXXXXX.hdf (0)
    Group size = 1
    Number of attributes = 5
        year = 2
        julian_date = 2
        start_time_utc = 1
        end_time_utc = 1
        pixels_per_degree = 1

在这里有什么打击你的奇怪吗?

1 个答案:

答案 0 :(得分:1)

您的错误是在H5Awrite()的电话中。

status = H5Awrite(attributeid, H5T_C_S1, attributevalue[0]);

这只写一个字符。由于H5T_C_S1的定义是

  

一个字节,以空字符结尾的八位字符串。

我通常会创建一个派生类型并设置它的大小。然后使用此类型调用H5Awrite,因为写调用会在内存类型中复制此大小。

这是一个简单的例子。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hdf5.h>

#define FILENAME "att_str.h5"

int main(){

        hid_t    fid;
        hid_t    att;
        hid_t    ds;
        hid_t    type;
        herr_t   status;
        char     x[] = "lah lah lah";
        int32_t  len = 0;

        fid     = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
        type    = H5Tcopy(H5T_C_S1);
        len     = strlen(x);
        status  = H5Tset_size(type, len);
        ds      = H5Screate(H5S_SCALAR);
        att     = H5Acreate(fid, "test", type, ds, H5P_DEFAULT, H5P_DEFAULT);
        status  = H5Awrite(att, type, &x);

        status  = H5Aclose(att);
        status  = H5Tclose(type);
        status  = H5Sclose(ds);
        status  = H5Fclose(fid);

        return(EXIT_SUCCESS);
}

编译并运行后,生成的文件包含:

HDF5 "att_str.h5" {
GROUP "/" {
   ATTRIBUTE "test" {
      DATATYPE  H5T_STRING {
         STRSIZE 11;
         STRPAD H5T_STR_NULLTERM;
         CSET H5T_CSET_ASCII;
         CTYPE H5T_C_S1;
      }
      DATASPACE  SCALAR
      DATA {
      (0): "lah lah lah"
      }
   }
}
}

注意我如何创建一个派生类型,它是要写入的字符串的长度:

len     = strlen(x);
status  = H5Tset_size(type, len);

HDF5组确实有example个可变长度属性。