Rust HDF5数据处理库hdf5-metno-sys的使用,支持气象和科学数据的HDF5格式高效读写与解析

Rust HDF5数据处理库hdf5-metno-sys的使用,支持气象和科学数据的HDF5格式高效读写与解析

hdf5-sys

这个crate提供了对HDF5 C库的直接绑定,并允许根据需要从C源代码构建库,以便静态链接。

静态链接

该crate支持链接到HDF5的静态构建版本。HDF5 C库是通过hdf5-src crate构建的,当设置static feature时会进行链接。下面列出了静态构建的可用选项。

目前构建的HDF5库版本是1.10.5,但后续可能会更新。

Crate features

可用的features会根据所选库的features自动检测。可以通过指定环境变量HDF5_DIR来始终覆盖所选的库。

通用features:

  • mpio: 启用MPI支持(静态模式不支持)
  • static: 从源代码构建HDF5 C库(见下面选项列表)

这些选项是互斥的。未来可能会支持这些组合。

以下features会影响从源代码编译HDF5时的构建选项:

  • hl: 启用高级功能(我们没有为其提供绑定)
  • threadsafe: 构建线程安全版本的库
  • zlib: 启用zlib过滤器支持
  • deprecated: 包含已弃用的符号(我们没有为其提供绑定)

注意: HDF5库有单独的BSD-style许可证。

示例代码

以下是一个使用hdf5-metno-sys库读写HDF5文件的完整示例:

use hdf5_metno_sys::hdf5::{H5Fopen, H5Fclose, H5F_ACC_RDONLY, hid_t};

fn main() -> Result<(), String> {
    // 打开HDF5文件
    let file_name = "example.h5".as_ptr() as *const i8;
    let file_id = unsafe { H5Fopen(file_name, H5F_ACC_RDONLY, hid_t::default()) };
    
    if file_id < 0 {
        return Err("Failed to open HDF5 file".to_string());
    }
    
    // 在这里进行数据处理...
    // 可以添加读取数据集、属性等操作
    
    // 关闭文件
    let status = unsafe { H5Fclose(file_id) };
    if status < 0 {
        return Err("Failed to close HDF5 file".to_string());
    }
    
    Ok(())
}

完整示例代码

以下是一个更完整的示例,展示如何读取和写入HDF5数据集:

use hdf5_metno_sys::hdf5::{
    H5Fcreate, H5Fclose, H5F_ACC_TRUNC, H5P_DEFAULT,
    H5Screate_simple, H5Sclose, H5Dcreate2, H5Dwrite, H5Dclose,
    H5Dopen2, H5Dread, H5T_NATIVE_INT, hid_t
};
use std::ptr;

fn main() -> Result<(), String> {
    // 创建新HDF5文件
    let file_name = "test.h5".as_ptr() as *const i8;
    let file_id = unsafe { H5Fcreate(file_name, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT) };
    if file_id < 0 {
        return Err("Failed to create HDF5 file".to_string());
    }

    // 创建2x3的整数数据集
    let dims = [2, 3];
    let space_id = unsafe { H5Screate_simple(2, dims.as_ptr(), ptr::null()) };
    if space_id < 0 {
        unsafe { H5Fclose(file_id) };
        return Err("Failed to create dataspace".to_string());
    }

    let dataset_name = "my_data".as_ptr() as *const i8;
    let dataset_id = unsafe {
        H5Dcreate2(
            file_id,
            dataset_name,
            H5T_NATIVE_INT,
            space_id,
            H5P_DEFAULT,
            H5P_DEFAULT,
            H5P_DEFAULT
        )
    };
    if dataset_id < 0 {
        unsafe { H5Sclose(space_id); H5Fclose(file_id) };
        return Err("Failed to create dataset".to_string());
    }

    // 写入数据
    let data = [1, 2, 3, 4, 5, 6];
    let status = unsafe {
        H5Dwrite(
            dataset_id,
            H5T_NATIVE_INT,
            H5S_ALL,
            H5S_ALL,
            H5P_DEFAULT,
            data.as_ptr() as *const _
        )
    };
    if status < 0 {
        unsafe { H5Dclose(dataset_id); H5Sclose(space_id); H5Fclose(file_id) };
        return Err("Failed to write data".to_string());
    }

    // 关闭资源
    unsafe {
        H5Dclose(dataset_id);
        H5Sclose(space_id);
        H5Fclose(file_id);
    }

    Ok(())
}

安装

在项目目录中运行以下Cargo命令:

cargo add hdf5-metno-sys

或者在Cargo.toml中添加:

hdf5-metno-sys = "0.10.1"

文档

该库的文档可在在线文档平台查看。

仓库

源代码位于开源代码托管平台。

所有者

Magnus Ulimoen

分类

  • 文件系统
  • FFI
  • 科学

1 回复

Rust HDF5数据处理库hdf5-metno-sys使用指南

简介

hdf5-metno-sys是Rust中一个专门用于处理HDF5格式数据的库,特别针对气象和科学数据进行了优化。它提供了高效读写和解析HDF5文件的能力,适合处理大规模科学数据集。

安装

在Cargo.toml中添加依赖:

[dependencies]
hdf5-metno-sys = "0.1"

基本使用方法

1. 打开HDF5文件

use hdf5_metno_sys::hdf5;

let file = hdf5::File::open("data.h5", "r").expect("无法打开HDF5文件");

2. 读取数据集

// 获取数据集
let dataset = file.dataset("temperature").expect("数据集不存在");

// 读取为f32数组
let data: Vec<f32> = dataset.read_raw().expect("读取数据失败");

3. 写入数据集

let file = hdf5::File::create("output.h5").expect("无法创建文件");

// 创建2D数据集
let dataset = file
    .create_dataset::<f64>("pressure")
    .shape(&[100, 100])
    .expect("无法创建数据集");

// 写入数据
let data = vec![0.0; 100 * 100];
dataset.write(&data).expect("写入数据失败");

高级功能

1. 处理属性

// 读取属性
let attr = dataset.attribute("units").expect("属性不存在");
let unit: String = attr.read_scalar().expect("读取属性失败");

// 写入属性
dataset.new_attribute::<&str>("description")
    .create("Sea surface temperature data")
    .expect("无法创建属性");

2. 处理气象数据特有的结构

// 读取时间维度数据
let time_var = file.datataset("time").expect("时间变量不存在");
let times: Vec<i64> = time_var.read_raw().expect("读取时间数据失败");

// 读取经纬度网格
let lat_var = file.dataset("lat").expect("纬度变量不存在");
let lats: Vec<f32> = lat_var.read_raw().expect("读取纬度数据失败");

3. 分块读取大数据集

// 分块读取大型数据集
let dataset = file.dataset("large_data").expect("数据集不存在");
let chunk_size = [100, 100];
let mut buffer = vec![0.0f32; chunk_size[0] * chunk_size[1]];

for i in 0..10 {
    let offset = [i * chunk_size[0], 0];
    dataset.read_slice(&mut buffer, offset, chunk_size).expect("读取分块失败");
    // 处理buffer中的数据...
}

完整示例:气象数据处理

use hdf5_metno_sys::hdf5;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 打开HDF5气象数据文件
    let file = hdf5::File::open("weather_data.h5", "r")?;
    
    // 2. 读取温度数据
    let temp_dataset = file.dataset("temperature")?;
    let temp_data: Vec<f32> = temp_dataset.read_raw()?;
    
    // 3. 读取纬度/经度数据
    let lats = file.dataset("lat")?.read_raw::<f32>()?;
    let lons = file.dataset("lon")?.read_raw::<f32>()?;
    
    // 4. 读取时间维度
    let times = file.dataset("time")?.read_raw::<i64>()?;
    
    // 5. 读取数据属性
    let unit_attr = temp_dataset.attribute("units")?;
    let units: String = unit_attr.read_scalar()?;
    
    println!("成功读取气象数据:");
    println!("- 温度数据点: {}个", temp_data.len());
    println!("- 纬度范围: {:.2}°N 到 {:.2}°N", lats[0], lats[lats.len()-1]);
    println!("- 经度范围: {:.2}°E 到 {:.2}°E", lons[0], lons[lons.len()-1]);
    println!("- 时间范围: {} 到 {}", times[0], times[times.len()-1]);
    println!("- 单位: {}", units);
    
    // 6. 处理数据示例 - 计算平均温度
    let sum: f32 = temp_data.iter().sum();
    let avg = sum / temp_data.len() as f32;
    println!("平均温度: {:.2}° {}", avg, units);
    
    Ok(())
}

性能提示

  1. 对于大型数据集,使用分块读取/写入
  2. 尽可能复用文件句柄而不是频繁开关文件
  3. 对于频繁访问的数据,考虑缓存到内存
  4. 使用正确的数据类型以减少内存占用

注意事项

  • 该库需要系统安装HDF5库
  • 处理大型数据集时注意内存使用
  • 写入操作会覆盖现有文件
  • 某些HDF5高级功能可能需要直接使用底层HDF5库
回到顶部