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(())
}
性能提示
- 对于大型数据集,使用分块读取/写入
- 尽可能复用文件句柄而不是频繁开关文件
- 对于频繁访问的数据,考虑缓存到内存
- 使用正确的数据类型以减少内存占用
注意事项
- 该库需要系统安装HDF5库
- 处理大型数据集时注意内存使用
- 写入操作会覆盖现有文件
- 某些HDF5高级功能可能需要直接使用底层HDF5库