You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Rust的hdf5-rust crate读取HDF5数据集的字符串属性?

问题描述

HDF5文件结构

通过h5dump查看的文件结构如下:

❯ h5dump -n GMTCO_npp_d20181005_t2022358_e2024003_b35959_c20181008035331888329_cspp_dev.h5
HDF5 "GMTCO_npp_d20181005_t2022358_e2024003_b35959_c20181008035331888329_cspp_dev.h5" {
FILE_CONTENTS {
 group      /
 group      /All_Data
 group      /All_Data/VIIRS-MOD-GEO-TC_All
 dataset    /All_Data/VIIRS-MOD-GEO-TC_All/Height
 dataset    /All_Data/VIIRS-MOD-GEO-TC_All/Latitude
 dataset    /All_Data/VIIRS-MOD-GEO-TC_All/Longitude
 ...
 group      /Data_Products
 group      /Data_Products/VIIRS-MOD-GEO-TC
 dataset    /Data_Products/VIIRS-MOD-GEO-TC/VIIRS-MOD-GEO-TC_Aggr
 dataset    /Data_Products/VIIRS-MOD-GEO-TC/VIIRS-MOD-GEO-TC_Gran_0
 }
}

目标属性信息

需要读取数据集/Data_Products/VIIRS-MOD-GEO-TC/VIIRS-MOD-GEO-TC_Gran_0的字符串属性N_Granule_ID,其元数据如下:

ATTRIBUTE "N_Granule_ID" {
   DATATYPE  H5T_STRING {
      STRSIZE 16;
      STRPAD H5T_STR_NULLTERM;
      CSET H5T_CSET_ASCII;
      CTYPE H5T_C_S1;
   }
   DATASPACE  SIMPLE { ( 1, 1 ) / ( 1, 1 ) }
   DATA {
   (0,0): "NPP002194429582"
   }
}

尝试的代码

use anyhow::{Ok, Result};
use hdf5::File;
use ndarray::{Array, Array2};

fn main() -> Result<()> {
    let filename = "GMTCO_npp_d20181005_t2022358_e2024003_b35959_c20181008035331888329_cspp_dev.h5".to_string();
    let file = File::open(filename)?;
    let dataset = file.dataset("Data_Products/VIIRS-MOD-GEO-TC/VIIRS-MOD-GEO-TC_Gran_0")?;
    let attribute = dataset.attr("N_Granule_ID")?;

    // Don't know what to use here...
    let v: Array2<String> = attribute.read_2d::<String>()?;

    Ok(())
}

遇到的问题

代码执行到读取属性内容时出错,根据属性元数据的DATASPACE SIMPLE { ( 1, 1 ) / ( 1, 1 ) },该属性是包含单个元素的2D数组,但不确定应该使用哪种读取方法和Rust数据类型。另外,hdf5-rust包仅提供了复合属性的读取示例,不清楚如何读取f32、i32、String这类非复合类型的属性。


解决方案

读取字符串属性

对于HDF5中的固定长度ASCII字符串属性,hdf5-rust提供了FixedAscii类型来匹配,再转换为Rust原生String即可。针对1x1的2D属性,代码如下:

use anyhow::{Ok, Result};
use hdf5::types::FixedAscii;
use hdf5::File;
use ndarray::Array2;

fn main() -> Result<()> {
    let filename = "GMTCO_npp_d20181005_t2022358_e2024003_b35959_c20181008035331888329_cspp_dev.h5".to_string();
    let file = File::open(filename)?;
    let dataset = file.dataset("Data_Products/VIIRS-MOD-GEO-TC/VIIRS-MOD-GEO-TC_Gran_0")?;
    let attribute = dataset.attr("N_Granule_ID")?;

    // 读取为1x1的FixedAscii数组,长度匹配属性的STRSIZE=16
    let str_array: Array2<FixedAscii<16>> = attribute.read_2d()?;
    // 去掉末尾空终止符并转换为String
    let granule_id: String = str_array[[0, 0]].trim_end_nul().to_string();
    
    println!("Granule ID: {}", granule_id); // 输出: NPP002194429582

    Ok(())
}
  • FixedAscii<N>对应HDF5中的固定长度ASCII字符串,N必须和属性元数据里的STRSIZE一致(这里是16)。
  • trim_end_nul()用于移除字符串末尾的空终止符,适配属性的STRPAD H5T_STR_NULLTERM设置。

读取数值类型属性(f32/i32)

对于f32、i32这类数值类型的属性,直接使用对应Rust类型读取即可,无需额外转换:

读取2D i32属性示例

// 假设属性是2D的i32类型
let int_array: Array2<i32> = attribute.read_2d()?;
let target_value = int_array[[0, 0]];

读取标量f32属性示例

如果属性是标量(DATASPACE为标量),使用read_scalar():

let float_value: f32 = attribute.read_scalar()?;

读取1D f32数组属性示例

// 读取为Vec<f32>
let float_vec: Vec<f32> = attribute.read_1d()?;
// 或读取为ndarray的Array1
let float_array: ndarray::Array1<f32> = attribute.read_1d()?;

内容的提问来源于stack exchange,提问作者geoff.cureton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:20:54