h5fopen 和 h5fcreate 前须校验路径与模式:h5fopen 要求文件存在,否则返回 0;h5fcreate 默认清空文件,需手动检查是否存在;hdf5 默认静默失败,c++ 需启用异常。

用 H5Fopen 和 H5Fcreate 打开/新建 HDF5 文件前,必须确认文件路径和访问模式是否匹配
常见错误是程序崩溃或返回 NULL,但没报具体错误——其实是因为 HDF5 默认静默失败,不抛异常。C++ 绑定(如 H5Cpp)默认也关异常,得手动开。
- 用
H5Fopen("data.h5", H5F_ACC_RDONLY, H5P_DEFAULT)时,文件必须存在,否则返回0(不是nullptr!),且不会提示“找不到” -
H5Fcreate("new.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)会清空已有文件;若想只在不存在时新建,得先用access("new.h5", F_OK)检查,HDF5 本身不提供“仅新建”标志 - Windows 下路径含中文或空格基本没问题,但某些旧版本 HDF5(\servershareile.h5)支持不稳定,建议映射为盘符
读写 dataset 时,H5Dread/H5Dwrite 的内存布局必须和 dataspace 严格一致
最常踩的坑:以为传个 std::vector<double></double> 就能直接读,结果数据全错位或越界。HDF5 不认 C++ 容器,只认连续内存块 + 显式维度描述。
- 写二维数组时,C 风格行优先(row-major)是默认,但如果你用
std::vector<:vector>></:vector>,它内存不连续,必须展平:std::vector<double> flat(data.size() * data[0].size())</double>,再按i * cols + j填充 - 读的时候同样要预分配好目标缓冲区大小,且用
H5S_ALL或自己创建dataspace描述维度;别指望 HDF5 自动 resize vector - 类型必须精确匹配:
H5T_NATIVE_DOUBLE对double,H5T_IEEE_F64LE是字节序敏感格式,跨平台读写慎用
用 H5Cpp.h 时,RAII 管理句柄比裸 C API 更安全,但析构顺序容易出问题
C++ 封装层(H5Cpp.h)让 H5File、DataSet 看起来像智能指针,但底层仍依赖 HDF5 的引用计数。对象销毁顺序不对,可能提前释放 dataspace 或 datatype。
- 不要把
DataSet存在局部作用域外而H5File已销毁——哪怕DataSet还活着,其内部hid_t可能已失效 -
DataSpace和DataType同样需在DataSet之前构造、之后析构;推荐在同一个作用域内声明,靠栈顺序保证 - 如果要用
shared_ptr包裹,必须自定义删除器调用H5*close(),不能只靠delete
大数组读写卡顿或 OOM,不是 HDF5 慢,而是没用 H5Sselect_hyperslab 分块
一次性读 GB 级 dataset 到内存,既慢又危险。HDF5 支持子集读写,但需要手动切分 dataspace,不是靠循环读 chunk——那是自己造轮子。
- 用
H5Sselect_hyperslab指定偏移(start[])和尺寸(count[]),再配一个内存 dataspace 描述目标缓冲区大小,就能读任意矩形区域 - 注意:文件 dataspace 和内存 dataspace 维度必须一致,但尺寸可以不同(比如文件是 10000×1000,内存 buffer 是 1000×1000)
- 并行读写(MPI-IO)需要
H5Pset_fapl_mpio,但单机多线程下,每个线程应操作独立H5File实例,共用一个文件句柄会竞争锁
HDF5 的复杂点不在 API 多,而在每个操作背后都隐含一个“空间描述+类型描述+属性列表”的三元组,漏掉任一环,错误信息就只报 H5I_INVALID_HID 或静默失败。调试时优先检查 hid_t 是否为正数,再看 dataspace 维度是否 match。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











