【问题标题】:Determine length of fixed-length string attribute from HDF5 file in C从C中的HDF5文件确定固定长度字符串属性的长度
【发布时间】:2021-12-27 03:32:18
【问题描述】:

我有一个包含以下内容的 HDF5 文件:

$ h5dump foo.h5 
HDF5 "foo.h5" {
GROUP "/" {
   ATTRIBUTE "Version" {
      DATATYPE  H5T_STRING {
         STRSIZE 5;
         STRPAD H5T_STR_NULLTERM;
         CSET H5T_CSET_ASCII;
         CTYPE H5T_C_S1;
      }
      DATASPACE  SIMPLE { ( 1 ) / ( 1 ) }
      DATA {
      (0): "1.2.0"
      }
   }
...

如何从属性中提取STRSIZE(在本例中为 5)?我目前可以通过分配比我认为需要的更多的内存来提取整个字符串:

char version_string[] = "hello_hello_hello";
hid_t attr = H5Aopen(file_id, "Version", H5P_DEFAULT);
hid_t atype = H5Tcopy(H5T_C_S1);
H5Tset_size(atype, 17);
herr_t err = H5Aread(attr, atype, version_string);
H5Aclose(attr);
H5Tclose(atype);

但是,我不知道如何找到为字符串分配内存的正确

【问题讨论】:

  • 您使用的是什么 HDF5 库和版本?
  • @Dai: HDF5 版本 1.12.1
  • 当您在H5Aread 中覆盖时,为什么version_string 具有来自字符串文字的初始内容?
  • 你为什么使用H5Tcopy?您应该可以将H5T_C_S1 直接传递给H5Aread
  • @Dai:它有初始内容,因为我是一个糟糕的 C 程序员并且试图避免使用 malloc。

标签: c hdf5


【解决方案1】:

使用HDFql 可以更轻松地在C 中处理HDF5 文件的另一种方法。分配适当的内存量来存储固定长度字符串的属性值可以按如下方式完成(在 C 中使用 HDFql):

long long size;

char *data;

hdfql_variable_transient_register(&size);

hdfql_execute("SHOW SIZE foo.h5 \"Version\" INTO MEMORY 0");

printf("String size: %lld\n", size);

data = malloc(size);

hdfql_variable_transient_register(&data);

hdfql_execute("SELECT FROM foo.h5 \"Version\" INTO MEMORY 0");

printf("String data: %s\n", data);

【讨论】:

  • 它确实似乎有一个设计更好的 API。不幸的是,我需要使用标准 API。 . .
【解决方案2】:

(免责声明:我不是 HDF5 用户)

通过查看文档,我认为您需要使用H5Aget_storage_size 来确定要与H5Aread 一起使用的缓冲区大小。

    hid_t versionAttr = H5Aopen( file_id, "Version", H5P_DEFAULT );
    if( versionAttr < 0 ) goto cleanup1;

    size_t versionAttrSize = 0;
    {
        hsize_t size = H5Aget_storage_size( versionAttr );
        if( size == 0 ) {
            // get_storage_size failed for some reason but the documentation isn't helpful. Grrrr.
            // TODO: Show an error message here, I guess.
            goto cleanup2;
        }
        else if( size > SIZE_MAX ) {
            // The data on-disk is larger than can be represented in C on your platform.
            // TODO: Show an error message here, I guess.
            goto cleanup2;
        }
        else {
            versionAttrSize = (size_t)size;
        }
    }

    char* versionAttrBuffer = malloc( versionAttrSize );
    if( !versionAttrBuffer ) {
        // Computer broken.
        goto cleanup2;
    }

    herr_t versionAttrBufferReadError = H5Aread( versionAttr, H5T_C_S1, versionAttrBuffer );
    if( versionAttrBufferReadError < 0 ) {
        goto cleanup3;
    }

    // Do stuff with `versionAttrBuffer` here.
    printf( "String attribute length: %d\n", versionAttrSize );
    printf( "String attribute data: \"%s\"", versionAttrBuffer );

cleanup3:
    free( versionAttrBuffer );

cleanup2:
    herr_t cleanupErr = H5Aclose( versionAttr );
    if( cleanupErr < 0 ) { die( "This should never happen." ); };

cleanup1:
    // TODO: Close file?

【讨论】:

  • 非常感谢!刚刚验证了这一点并在 ASan 下运行它;它有效。
猜你喜欢
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多