使用Fortran读取HDF5数据
使用Fortran读取HDF5数据
下面我将介绍如何在Fortran中读取HDF5文件中的各种类型数组数据,包括一维数组、二维数组、元数组和变长数组。
准备工作
首先需要确保系统安装了HDF5库,并且在编译时链接了HDF5库。例如使用gfortran编译时:
gfortran -o hdf5_example hdf5_example.f90 -I/path/to/hdf5/include -L/path/to/hdf5/lib -lhdf5_fortran -lhdf5
基本代码框架
program hdf5_read_example
use hdf5
implicit none
! 声明变量
integer :: hdferr
integer(hid_t) :: file_id, dataset_id, dataspace_id
integer(hsize_t), dimension(2) :: dims, maxdims
integer :: rank
! 初始化HDF5库
call h5open_f(hdferr)
if (hdferr /= 0) then
write(*,*) "Error initializing HDF5 library"
stop
end if
! 打开HDF5文件
call h5fopen_f("example.h5", H5F_ACC_RDONLY_F, file_id, hdferr)
if (hdferr /= 0) then
write(*,*) "Error opening HDF5 file"
stop
end if
! 在这里添加读取不同数据集的代码
! 关闭文件
call h5fclose_f(file_id, hdferr)
! 关闭HDF5库
call h5close_f(hdferr)
end program hdf5_read_example
1. 读取一维数组
subroutine read_1d_array(file_id)
use hdf5
implicit none
integer(hid_t), intent(in) :: file_id
integer :: hdferr
integer(hid_t) :: dataset_id
integer(hsize_t), dimension(1) :: dims
real, allocatable :: data_1d(:)
! 打开数据集
call h5dopen_f(file_id, "/1d_array", dataset_id, hdferr)
! 获取数据集维度
call h5dget_space_f(dataset_id, dataspace_id, hdferr)
call h5sget_simple_extent_dims_f(dataspace_id, dims, maxdims, hdferr)
! 分配内存
allocate(data_1d(dims(1)))
! 读取数据
call h5dread_f(dataset_id, H5T_NATIVE_REAL, data_1d, dims, hdferr)
! 输出数据
write(*,*) "1D Array:"
write(*,*) data_1d
! 清理
deallocate(data_1d)
call h5dclose_f(dataset_id, hdferr)
end subroutine read_1d_array
2. 读取二维数组
subroutine read_2d_array(file_id)
use hdf5
implicit none
integer(hid_t), intent(in) :: file_id
integer :: hdferr
integer(hid_t) :: dataset_id, dataspace_id
integer(hsize_t), dimension(2) :: dims
real, allocatable :: data_2d(:,:)
! 打开数据集
call h5dopen_f(file_id, "/2d_array", dataset_id, hdferr)
! 获取数据集维度
call h5dget_space_f(dataset_id, dataspace_id, hdferr)
call h5sget_simple_extent_dims_f(dataspace_id, dims, maxdims, hdferr)
! 分配内存
allocate(data_2d(dims(1), dims(2)))
! 读取数据
call h5dread_f(dataset_id, H5T_NATIVE_REAL, data_2d, dims, hdferr)
! 输出数据
write(*,*) "2D Array:"
do i = 1, dims(1)
write(*,*) data_2d(i,:)
end do
! 清理
deallocate(data_2d)
call h5dclose_f(dataset_id, hdferr)
end subroutine read_2d_array
3. 读取元数组(复合数据类型)
subroutine read_compound_array(file_id)
use hdf5
implicit none
integer(hid_t), intent(in) :: file_id
integer :: hdferr
integer(hid_t) :: dataset_id, datatype_id
integer(hsize_t), dimension(1) :: dims
integer :: i
! 定义复合数据类型
type compound_type
real :: temperature
integer :: pressure
character(len=10) :: name
end type compound_type
type(compound_type), allocatable :: compound_data(:)
! 打开数据集
call h5dopen_f(file_id, "/compound_data", dataset_id, hdferr)
! 获取数据集维度
call h5dget_space_f(dataset_id, dataspace_id, hdferr)
call h5sget_simple_extent_dims_f(dataspace_id, dims, maxdims, hdferr)
! 分配内存
allocate(compound_data(dims(1)))
! 创建内存中的复合数据类型
call h5tcreate_f(H5T_COMPOUND_F, sizeof(compound_data(1)), datatype_id, hdferr)
call h5tinsert_f(datatype_id, "temperature", 0, H5T_NATIVE_REAL, hdferr)
call h5tinsert_f(datatype_id, "pressure", sizeof(real), H5T_NATIVE_INTEGER, hdferr)
call h5tinsert_f(datatype_id, "name", sizeof(real)+sizeof(integer), H5T_C_S1, hdferr)
! 读取数据
call h5dread_f(dataset_id, datatype_id, compound_data, dims, hdferr)
! 输出数据
write(*,*) "Compound Data:"
do i = 1, dims(1)
write(*,*) compound_data(i)%temperature, compound_data(i)%pressure, trim(compound_data(i)%name)
end do
! 清理
deallocate(compound_data)
call h5tclose_f(datatype_id, hdferr)
call h5dclose_f(dataset_id, hdferr)
end subroutine read_compound_array
4. 读取变长数组
subroutine read_vlen_array(file_id)
use hdf5
implicit none
integer(hid_t), intent(in) :: file_id
integer :: hdferr
integer(hid_t) :: dataset_id, datatype_id, space_id, base_type_id
integer(hsize_t), dimension(1) :: dims
integer(hsize_t) :: num_elements
integer :: i, j
! 定义变长数组类型
type h5_vlen_t
integer(hsize_t) :: len
real, pointer :: data(:)
end type h5_vlen_t
type(h5_vlen_t), allocatable :: vlen_data(:)
! 打开数据集
call h5dopen_f(file_id, "/vlen_array", dataset_id, hdferr)
! 获取数据集维度
call h5dget_space_f(dataset_id, space_id, hdferr)
call h5sget_simple_extent_dims_f(space_id, dims, maxdims, hdferr)
! 分配内存
allocate(vlen_data(dims(1)))
! 创建变长数据类型
call h5tcopy_f(H5T_NATIVE_REAL, base_type_id, hdferr)
call h5tvlen_create_f(base_type_id, datatype_id, hdferr)
! 读取数据
call h5dread_f(dataset_id, datatype_id, vlen_data, dims, hdferr)
! 输出数据
write(*,*) "Variable-length Array:"
do i = 1, dims(1)
write(*,'(A,I0,A)', advance='no') "Element ", i, ": "
do j = 1, vlen_data(i)%len
write(*,'(F8.2)', advance='no') vlen_data(i)%data(j)
end do
write(*,*)
end do
! 释放变长数组内存
do i = 1, dims(1)
deallocate(vlen_data(i)%data)
end do
! 清理
deallocate(vlen_data)
call h5tclose_f(datatype_id, hdferr)
call h5tclose_f(base_type_id, hdferr)
call h5dclose_f(dataset_id, hdferr)
end subroutine read_vlen_array
完整示例
program hdf5_read_example
use hdf5
implicit none
integer :: hdferr
integer(hid_t) :: file_id
! 初始化HDF5库
call h5open_f(hdferr)
! 打开HDF5文件
call h5fopen_f("example.h5", H5F_ACC_RDONLY_F, file_id, hdferr)
! 读取各种类型的数据
call read_1d_array(file_id)
call read_2d_array(file_id)
call read_compound_array(file_id)
call read_vlen_array(file_id)
! 关闭文件
call h5fclose_f(file_id, hdferr)
! 关闭HDF5库
call h5close_f(hdferr)
contains
! 在这里包含上面所有的子程序
! ...
end program hdf5_read_example
注意事项
- 错误处理:在实际应用中,应该对每个HDF5调用进行错误检查
- 内存管理:特别是对于变长数组,需要正确释放内存
- 数据类型匹配:确保HDF5文件中的数据类型与程序中读取的数据类型匹配
- 路径处理:数据集路径需要与HDF5文件中的实际路径一致
以上代码提供了Fortran读取HDF5中各种类型数组的基本框架,可以根据实际需求进行修改和扩展。