golang_操作HDF5文件_gonum/hdf5_linux_libhdf5-dev_遍历文件结构
转载注明来源: 本文链接 来自osnosn的博客,写于 2022-01-22.
参考
笔记
- Debian-11 需要
apt install libhdf5-dev
(安装成功。是 hdf5-1.10.6) - CentOS-8 需要
yum install hdf5-devel
(需要epel)- 如果提示:安装失败,包冲突。启用
yum config-manager --enable powertools
,就可以安装了。
版本较低, 是 hdf5-1.10.5
- 如果提示:安装失败,包冲突。启用
- 另一个选择,去下载源码包 然后
./configure --prefix=/usr/local/hdf5
make
make check
make install
通过源码安装。可以安装最新的。 - 参考 【gonum/hdf5/cmd】中的例子。
遍历hdf5结构 (不能遍历属性)
//filename: read_hdf5.go
package main
import (
"flag"
"fmt"
"gonum.org/v1/hdf5"
)
func main() {
hdf5_filename := "" //命令行参数,hdf5文件名
flag.StringVar(&hdf5_filename, "f", "", "hdf5 filename")
flag.Parse()
if len(hdf5_filename) < 2 {
fmt.Printf("hdf5 file missing!\n")
return
}
fmt.Println()
//版本号
version, err := hdf5.LibVersion()
if err != nil {
fmt.Printf("** error ** %s\n", err)
return
}
fmt.Printf("=== version: %s ===\n", version)
// check hdf5 file
if !hdf5.IsHDF5(hdf5_filename) {
fmt.Printf("\"%s\" Not a hdf5 file!\n", hdf5_filename)
return
}
// open hdf5 file
ff, err := hdf5.OpenFile(hdf5_filename, hdf5.F_ACC_RDONLY)
if err != nil {
panic(err)
}
fmt.Printf("=== hdf5 opened.\n")
//显示hdf5 结构, 仅支持 group,dataset 两种
prefix := " " //至少一个空格
Show_h5(prefix, &ff.CommonFG)
fmt.Printf("=== close hdf5.\n")
ff.Close()
}
func Show_h5(prefix string, obj *hdf5.CommonFG) {
//显示当前节点的 名称,类型
fmt.Printf("%s(%s) %s \n", prefix, obj.Type(), obj.Name())
//获取当前节点中包含的,下级节点数目
ObjNum, _ := obj.NumObjects()
if ObjNum < 1 {
return
}
prefix = prefix[:len(prefix)-1] + " |-" //前缀,缩进一层
for ii := uint(0); ii < ObjNum; ii++ {
ObjName, _ := obj.ObjectNameByIndex(ii) //节点name
ObjType, _ := obj.ObjectTypeByIndex(ii) //节点type
if ObjType == hdf5.H5G_GROUP { //是GROUP
//fmt.Printf("%s(%s) %s \n", prefix, ObjType, ObjName)
obj, _ := obj.OpenGroup(ObjName)
Show_h5(prefix, &obj.CommonFG) //递归调用
obj.Close()
} else if ObjType == hdf5.H5G_DATASET { //是DATASET
fmt.Printf("%s(%s) %s \n", prefix, ObjType, ObjName)
}
}
}
- 编译,执行
go build read_hdf5.go
./read_hdf5 -f xxxx.hdf5
- 无法遍历 属性
- hdf5 group 官网
Documentation
->HDF5
->HDF5 Examples
->【Examples in the Source Code】的例子 【h5_attribute.c】 中,给出了在 C++ 中遍历属性的方法。用到了H5Oget_info3()
或H5Aiterate2()
。Documentation
->HDF5
->HDF5 User Guides
->HDF5 User's Guide
也写了。
- 可是 gonum/hdf5 并没有封装这两个函数(2022-01)。
- hdf5 group 官网
- 属性,无法获取它的 Datatype,应该是没封装这个功能(2022-01)。
读取hdf5的dataset中的属性
// 或者 obj = & hdf5_fd.CommonFG // hdf5_fd = hdf5.OpenFile( ... )
// 或者 obj = & group.CommonFG // group = xxx.OpenGroup( ... )
dset, _ := obj.OpenDataset("mydataset")
attName := "Description" //字符串类型的属性
att, err := dset.OpenAttribute(attName)
if err == nil {
var buf string
att.Read(&buf, hdf5.T_GO_STRING)
buflen := len(buf)
fmt.Printf(" %s=%s (%d)\n", attName, buf, buflen)
att.Close()
}
attName = "Rate" //float32 类型的属性
att, err = dset.OpenAttribute(attName)
if err == nil {
var rate float32
att.Read(&rate, hdf5.T_NATIVE_FLOAT)
fmt.Printf(" %s=%.3f \n", attName, rate)
att.Close()
}
dset.Close()
- 属性,无法获取它的 Datatype,应该是没封装这个功能(2022-01)。
- 指定 float32 属性的读取,没问题。
- 指定 string 属性的读取。有的读取正常,有的会多读出几个字节的乱码。我也无法解决。估计是 gonum/hdf5 封装的问题。
用系统自带的hdf5-tools(C写的工具),读取string的属性,很正常。- 系统debian-11, 装的是hdf5-1.10.6 , gonum/hdf5 是最新的包(2022-01)。
- 无法获取单条记录的总大小,itemsize。(2022-01)
- 读取数据可以用 []byte 做 buffer,用 encoding/binary 包,LittleEndian 解析。
- 总之,gonum/hdf5 远未完成。没法使用。(2022-01)
静态编译
CGO_ENABLED=1 go build -v -ldflags '-w -s -extldflags "-static -lhdf5 -lhdf5_hl -lhdf5_serial -lhdf5_serial_hl -lm -ldl -lz -lsz -laec"' xxx.go
会有个warning,说 hdf5 用了 dl 库的 dlopen,会在运行中加载 glibc 动态库。
所以,静态编译的程序,需要在有相同 glibc 的系统中。- 我测试,debian中编译的,在centos中运行会有问题,只要操作hdf5文件,就会出错退出。
但可以在别的,没装hdf5库的debian中运行,操作hdf5文件。
- 我测试,debian中编译的,在centos中运行会有问题,只要操作hdf5文件,就会出错退出。
使用一个hdf5的旧库
- github.com/sbinet/go-hdf5
package main import ( "fmt" "github.com/sbinet/go-hdf5" ) func main() { fmt.Println("=== go-hdf5 ===") version, err := hdf5.LibVersion() if err != nil { fmt.Printf("** error ** %s\n", err) return } fmt.Printf("=== version: %s", version) fmt.Println("=== bye.") }
go build
出错,显示h5t_shim.go:259:5: constant 18446744073709551615 overflows int64
原因是H5Tpublic.h
中定义的H5T_VARIABLE类型是size_t实际是long unsigned int
(C语言),
而go-hdf5中定义的类型是 int64(golang),对应是long signed long
(C语言)。
去官网搜索一下hdf5库
- 去
https://pkg.go.dev/
搜索hdf5
,发现有好几个。没有一个可以用。
转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/15834309.html
来自 osnosn的博客 https://www.cnblogs.com/osnosn/ .