HDF5与文件夹有什么不同?

69 投票
9 回答
20911 浏览
提问于 2025-04-17 20:29

我正在做一个开源项目,这个项目是为了给文件夹添加元数据。提供的(Python)API让你可以像浏览普通文件夹一样浏览和访问这些元数据。因为它本质上就是一个普通的文件夹。

\folder\.meta\folder\somedata.json

然后我发现了HDF5和它的衍生版本Alembic

我在阅读关于HDF5的书籍《Python与HDF5》时,想了解使用它相比于使用文件夹中的文件有什么好处,但大多数资料都在讲它的层次化文件格式的优点,尤其是在通过API添加数据时的简单性:

>>> import h5py
>>> f = h5py.File("weather.hdf5")
>>> f["/15/temperature"] = 21

或者它可以根据请求只读取某些部分(比如随机访问),以及对单个HDF5文件的并行执行(例如用于多进程处理)。

你可以挂载HDF5文件,https://github.com/zjttoefs/hdfuse5

它甚至有一个强大而简单的基础概念,即数据集,维基百科上是这样描述的:

  • 数据集是同类类型的多维数组
  • 组是可以容纳数据集和其他组的容器结构

数据集替换成文件,把替换成文件夹,那么这些功能听起来就像是文件夹中的文件已经能够做到的事情。

我看到的每一个好处中,没有一个是HDF5独有的。

所以我的问题是,如果我给你一个HDF5文件和一个包含文件的文件夹,内容完全相同,那么在什么情况下HDF5会更适合呢?

编辑:

我收到了一些关于HDF5可移植性的回复。

这听起来不错,但我仍然没有得到一个例子,或者一个场景,说明HDF5会比文件夹更好。为什么有人会考虑使用HDF5,而不是普通文件夹,因为文件夹在任何电脑、任何文件系统上都能读取,通过网络也能访问,支持“并行输入输出”,而且人类可以不需要HDF5解释器就能读取。

我甚至可以说,包含文件的文件夹比任何HDF5都更具可移植性。

编辑2:

Thucydides411刚刚给出了一个可移植性重要的场景示例。https://stackoverflow.com/a/28512028/478949

我从这个讨论中得到的结论是,HDF5非常适合需要文件和文件夹的组织结构的情况,比如上面的示例场景,涉及大量(数百万个)小的数据结构(大约1字节),比如单个数字或字符串。它弥补了文件系统的不足,提供了一个“子文件系统”,更适合处理小而多的数据,而不是少而大的数据。

在计算机图形学中,我们用它来存储几何模型和关于单个顶点的任意数据,这似乎与它在科学界的使用非常契合。

9 个回答

2

在我看来,我们可以把文件夹和文件跟HDF5进行比较,但这主要是在科学数据的背景下,因为在这里,最重要的数据是由一组元数据描述的数组。

在一般情况下,Marcus说文件夹和文件比任何HDF5都更便携,这一点是对的。我还想补充一点,在一般情况下,文件夹和文件比HDF5文件更容易访问。显而易见的挑战是,使用“普通”的文件夹和文件时,不需要额外的API来访问数据。而HDF5则不一样,它把数据和元数据都放在同一个文件里,这样就不太方便了。

想象一下,如果你要阅读你的pdf文件,你需要一个新的pdf阅读器来理解HDF5格式?再想象一下,如果你要播放音乐,你需要一个能解码HDF5的音乐播放器?或者说,要运行你的python脚本,python解释器首先需要解码HDF5?总之,要启动你的python解释器,你的操作系统需要先解码HDF5?等等。如果真是这样,我根本无法写下这个回答,因为我的操作系统根本无法启动我的网页浏览器,而浏览器又无法读取它的内部文件,因为我之前把所有东西都变成了HDF5格式(也许是把我硬盘里的所有东西都放在一个大的HDF5文件里)。

把元数据存储在单独的文件里有一个巨大的好处,就是可以很好地与已经存在的大量数据文件和软件兼容,而不会增加额外的麻烦。

希望这能帮到你。

2

我觉得HDF5最大的好处就是可移植性

HDF5可以存储关于你的数据集的信息,比如大小、类型,以及整数和浮点数的字节顺序。这意味着你可以随意移动一个hdf5文件,甚至在不同类型的电脑上读取它的内容。

你还可以给组和数据集添加任意的元数据。其实,如果你的文件系统支持扩展属性,文件和文件夹也可以做到这一点。

一个hdf5文件就是一个单独的文件,这样有时候比把文件夹和文件压缩成zip或tar格式要方便得多。不过,这也有一个大缺点:如果你删除了一个数据集,你就不能回收那部分空间,除非你创建一个新文件。

总的来说,HDF5非常适合存储大量数字,通常用于科学数据集。

4

我现在正在评估HDF5,所以也有同样的问题。

这篇文章 – 告别HDF5 – 也在问差不多的问题。文章提到了一些很好的观点,比如HDF5库只有一个实现,而这个实现是在现代开源标准下相对不透明的情况下开发的。

从标题上可以看出,作者们决定不再使用HDF5,而是转向一种文件系统结构,使用二进制文件来存储数组,并在JSON文件中包含元数据。尽管他们在HDF5上投入了不少,但还是因为数据损坏和性能问题而感到失望。

12

谢谢你提出这个有趣的问题。一个文件夹里的文件能不能被称为“可移动的”,是因为我可以把一个目录复制到Mac的U盘上,然后在PC上看到同样的目录和文件吗?我同意文件目录结构是可移动的,这要感谢那些编写操作系统的人,但这和文件里的数据是否可移动没有关系。现在,如果这个目录里的文件是PDF格式的,那它们是可移动的,因为有工具可以在多个操作系统上读取和理解PDF文件(这要感谢Adobe)。但是,如果这些文件是原始的科学数据(无论是ASCII格式还是二进制格式都没关系),那它们就完全不可移动。ASCII文件看起来像一堆字符,而二进制文件则像是乱码。如果是XML或JSON文件,它们是可以被读取的,因为JSON是ASCII格式的,但它们所包含的信息可能不太可移动,因为XML/JSON标签的含义对没有写过这个文件的人来说可能不太清楚。这是一个重要的点,ASCII文件里的字符是可移动的,但它们所代表的信息却不是。

HDF5数据是可移动的,就像PDF一样,因为在许多操作系统中都有工具可以读取HDF5文件里的数据(就像PDF阅读器一样,见http://www.hdfgroup.org/products/hdf5_tools/index.html)。还有很多编程语言的库可以用来读取这些数据,并以用户能理解的方式展示出来——这就像Adobe Reader所做的那样。HDF5社区里有成百上千的团队为他们的用户做同样的事情(见http://www.hdfgroup.org/HDF5/users5.html)。

这里也讨论了一些关于压缩的内容。关于HDF5文件压缩的重要一点是,文件里的对象是独立压缩的,只有你需要的对象在输出时才会被解压。这显然比压缩整个文件然后再解压整个文件来读取要高效得多。

另一个关键点是,HDF5文件是自描述的——所以,写文件的人可以添加一些信息,帮助用户和工具了解文件里有什么。比如变量是什么,它们的类型是什么,哪个软件写的,哪个仪器收集的,等等。听起来你正在开发的工具可以读取文件的元数据。HDF5文件中的属性可以附加到文件里的任何对象上——它们不仅仅是文件级别的信息。这是非常重要的。当然,这些属性可以通过用多种语言和操作系统编写的工具来读取。

89

作为一个曾经把科学项目从使用文件夹和文件转到使用HDF5的人,我想分享一下HDF5的好处。

刚开始我的项目时,我处理的是小规模的测试数据集,输出的数据量也很小,只有几千字节。我最开始用的是最简单的数据格式,就是用ASCII编码的表格。每处理一个对象,我就会生成一个ASCII表格。

后来我开始对一组对象进行处理,这就意味着每次运行结束时,我需要写多个ASCII表格,还要再写一个包含整个组输出的ASCII表格。这样一来,我每组的数据就变成了一个文件夹,内容大概是这样的:

+ group
|    |-- object 1
|    |-- object 2
|    |-- ...
|    |-- object N
|    |-- summary

到这个时候,我开始遇到一些困难。ASCII文件读写速度很慢,而且存储数字信息的效率也不高,因为每个数字都要占用一个完整的字节,而不是大约3.3位。所以我决定把每个对象写成自定义的二进制文件,这样可以加快读写速度,减少文件大小。

随着我处理的组数越来越多(从几万到几百万),我突然发现自己要面对大量的文件和文件夹。文件太多会给很多文件系统带来问题(许多文件系统对可以存储的文件数量有限制,不管硬盘空间有多少)。我还发现,当我尝试对整个数据集进行后处理时,读取很多小文件的磁盘I/O开始占用不少时间。为了解决这些问题,我尝试把文件合并,这样每组只生成两个文件:

+ group 1
|    |-- objects
|    |-- summary
+ group 2
|    |-- objects
|    |-- summary
...

我还想压缩我的数据,所以开始为一组组的数据创建.tar.gz文件。

到这个时候,我的数据管理方式变得非常繁琐,如果我想把数据交给别人,解释起来会很麻烦。例如,包含对象的二进制文件有自己的内部结构,这些信息只存在于一个README文件和我办公室的一张纸上。想要读取我的合并对象二进制文件的人,必须知道每个元数据条目的字节偏移、类型和字节序,以及文件中每个对象的字节偏移。如果他们不知道这些,文件对他们来说就像是一堆乱码。

我对数据的分组和压缩方式也有问题。假设我想找一个对象,我得先找到它所在的.tar.gz文件,解压整个档案到一个临时文件夹,找到我感兴趣的组,然后用我自己定制的API来读取二进制文件。完成后,我还得删除临时解压的文件。这显然不是个优雅的解决方案。

于是,我决定换用标准格式。HDF5吸引我的原因有很多。首先,我可以把数据整体组织成组、对象数据集和汇总数据集。其次,我可以放弃自定义的二进制文件读写API,直接用多维数组数据集来存储组中的所有对象。我甚至可以创建更复杂数据类型的数组,比如包含C结构体的数组,而不需要详细记录每个条目的字节偏移。接下来,HDF5还有分块压缩,这对最终用户来说是完全透明的。因为压缩是分块的,如果我认为用户会想查看单个对象,我可以把每个对象压缩成一个单独的块,这样用户只需要解压他们感兴趣的数据部分。分块压缩是一个非常强大的功能。

最后,我现在只需要给别人一个文件,就不需要详细解释它的内部组织结构。最终用户可以用Python、C、Fortran,或者在命令行和图形界面HDFView中读取这个文件,查看里面的内容。这在我自定义的二进制格式和.tar.gz集合中是做不到的。

当然,用文件夹、ASCII和自定义二进制文件也可以实现HDF5的所有功能。这就是我最开始的做法,但这变成了一个大麻烦,最终HDF5以高效和可移植的方式完成了我之前拼凑起来的所有工作。

撰写回答