读取大型二进制文件

3
我正在处理一个项目,需要将一些信号(1D arrays)记录到二进制文件中。我可以存储大量的数据(通常是几个Giga字节)。现在我想要将这些文件加载回来。
我有两个可视化组件,一个称为“总览”,另一个只是一个普通的Y/T图表。总览应该让用户了解完整文件中的内容(大文件),而图表只显示文件的一部分,通常是概述中选择的具有可调整大小的矩形/带的部分。
因为文件可以非常大,将其加载到内存中并不是最优的,所以主要思路是仅将重要数据/可见数据(最多数MB)加载到内存中。因此,加载和显示是根据用户需求进行的。如果用户对图表进行缩放,则需要从文件中重新加载更多数据点。
我的问题是如何绘制概述组件以最佳方式显示文件的全部内容(无需实际从文件中加载所有样本)。假设我的文件大小超过10GB,我想让用户了解文件中的内容,但我可以在概述组件上绘制最多16k个样本?
是否有任何方法在记录日志时存储任何其他数据(例如索引,较小的数据块,图像...)以供稍后加载和绘制总览组件?目前,我只存储样本,但添加其他数据不会成为问题。您是否有任何相关经验,并且如何处理?
为了了解我正在做什么,请参见下图:

我真的不太明白这个问题。只读取文件的一部分是很容易的。 - David Heffernan
1
文件中有大量的样本。为了概述,我需要展示完整的文件,但是如果我不能在屏幕上显示所有数据,加载完整的文件就没有意义了,但我仍然必须向用户提供文件的概述。对于图表部分,我只显示/加载用户在概述窗口中用红色矩形选择的文件部分。然而,“最坏”的情况是选择完整的概述窗口,这意味着我必须重新加载完整的文件,但是我仍然不能这样做...只能每隔N个样本重新加载一次。我希望我已经解释清楚了。 - Nix
不是很确切。听起来含糊。 - David Heffernan
假设我有一个超过10G样本的大文件。为了绘制概览,我必须虚拟显示所有这些10GB样本,但有两件事情需要考虑。首先是我不能只将所有样本加载到内存中,其次是在屏幕上绘制10GB点根本不高效。基本上,我必须绘制文件的波形,但我不需要所有数据,因为它只是一个概览。所以我必须将所有这些10GB的内容虚拟地塞入16kSamples的概览缓冲区中。那么如何绘制这样的波形呢? - Nix
1
“一些信号(1D数组)”这并不是足够详细的信息。答案很大程度上取决于您的文件结构。请更详细地描述它(例如),或者如果它还没有确定,请描述文件结构应具备的要求。 - Jan Doggen
显示剩余3条评论
2个回答

3
你可以使用多级抽样 - 只存储每个Nth、N^2th等样本(例如,第10个,第100个,第1000个,第10000个...)。当用户更改窗口大小时,选择适当的级别,在此窗口中包含大约1000个样本,快速加载和显示这些样本(1000个点只是屏幕上图表的合理数量)。
如果您的数据具有某些特征或奇特性质,则可以获得更大(升级)的数据集,并应用Douglas-Peucker 折线简化算法以保留这些特征。

为什么选择10作为基数? - David Heffernan
这很有道理。我现在明白了。也许我唯一看到的问题是,信号应该适用于奈奎斯特定理,可能我应该进行一些过滤以避免反混叠。这基本上是重新采样。我会按照这种方式查找,听起来很有前途,而且很有道理。我听说过道格拉斯-普克算法,但从未考虑过它。处理大数据并提取有用信息是一个相当大的挑战。感谢您的想法。 - Nix
@David 10只是一个例子。 - MBo
我查看了Audacity源代码,他们正在对波形文件进行某种缓存。只有在必要时(即放大时)才绘制所有点。我仍然需要深入挖掘以获取更多信息,但我已经基本了解了这个想法。 - Nix
1
根据数据,您可能希望获取一定数量样本的平均值或均值,以显示缩小的部分。 - Gregor Brandt

1
当我写入文件时,我会写入几个具有固定大小的数据块(大小取决于DAQ采样率)。在写入了固定数量的这些块之后,我会添加一个统计块,其中包含有关已写入的数据块数以及从所有已写入的数据块中计算出的最大值、最小值、平均值和方差的信息。然后我会重复这个过程……直到用户停止录制为止。
File struct is:

[File header]
[DataChunk1]
[DataChunk2]
...
[DataChunkN]
[StatsChunk1]
[DataChunkN+1]
[DataChunkN+2]
...
[DataChunkN+..]
[StatsChunk2]
....

当我想加载文件并绘制数据时,我只需要重新计算当前在图表上设置的数据/像素比率。有两种情况。如果缩放真的很小,因此数据/像素比率<=1,我需要从文件中加载适当数量的数据块(从数据块中)并在图表上显示它(必要时进行一些插值)。绘图很简单...只需从点到点画线,因为我们正在显示所有数据。
如果比率大于1,则加载适当数量的统计块(而不是数据块)并使用它们来绘制图表。首先,我会绘制一个包络线,其中包含最小值和最大值(两个带有涂色区域的系列),然后我会绘制一个平均值+/-标准偏差(sqrt(方差))的系列。这样我就可以显示这些块中的数据概述。因为我只读取统计块,所以读取性能非常好(快)。如果文件足够大,以至于统计块数/像素比率大于1,那么我可以简单地对统计块进行抽稀并进行绘制。
关于要加载的块数等等...我必须进行一些实验,以看看哪些给我最好的结果,但是第一次尝试非常鼓舞人心。稍后我将添加一些关于最终结果的评论和照片以展示它。感谢您的想法和贡献。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接