读取大文件(> 2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是啥?

Posted

技术标签:

【中文标题】读取大文件(> 2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是啥?【英文标题】:What is the best way to read large file (>2GB) (Text file contains ethernet data) and access the data randomly by different parameters?读取大文件(> 2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么? 【发布时间】:2020-01-24 09:46:45 【问题描述】:

我有一个如下所示的文本文件:

0.001 ETH Rx 1 1 0 B45678810000000000000000AF0000 555
0.002 ETH Rx 1 1 0 B45678810000000000000000AF 23
0.003 ETH Rx 1 1 0 B45678810000000000000000AF156500
0.004 ETH Rx 1 1 0 B45678810000000000000000AF00000000635254

我需要一种方法来读取此文件并形成一个结构并将其发送到客户端应用程序。

目前,我可以借助 Boost 的循环队列来做到这一点。

这里需要在不同的时间访问不同的数据。

例如:如果我想在 0.03 秒 访问数据,而我目前在 100 秒,我怎样才能以最好的方式做到这一点,而不是让文件指针跟踪,或将整个文件保存到内存中导致性能瓶颈? (考虑到我有一个大小为 2 GB 的文件,其中包含上述类型的数据)

【问题讨论】:

使用数据库。 嗨@HongOoi,使用数据库很好。如何随机访问数据? 你可以进行二分搜索。 在这个例子中,每一行都有完全相同的字节长度,第一列是定义良好的算术链。如果所有行都是这样,那么在行之间跳转就很容易了。 嗨@MarekR 该文件可能包含每行不同的字节长度 【参考方案1】:

通常处理大文件的最佳实践取决于平台架构(x86/x64)和操作系统(Windows/Linux 等)

既然你提到了 boost,你有没有考虑过使用 boost 内存映射文件? Boost Memory Mapped File

【讨论】:

嗨,苏里亚,感谢您提供的信息。我想在 Windows 和 linux 上都使用它。如果我使用 Boost Memory Mapped 文件,如何随机访问数据?如果文件大小增加,这种情况下性能可能会下降 Boost Memory Mapped 文件兼容 Windows 和 POSIX。使用 data() 和 size_of_record * number of records 来寻找你可以执行随机访问。查找 new_location = data() + (size_of_record * number_of_records) 并将 new_location 存储为指向记录的指针。性能仅在发生页面错误时才会受到影响,因此与其他大文件读取方法相比,性能不会显着下降。 嗨,苏里亚,谢谢。我会试试这个,看看性能。顺便说一句,对 hdf5 库有什么想法吗? 每行的字节数不同。每个帧可能包含可变长度的数据。在这种情况下,获取新的位置数据是不可能的吧?【参考方案2】:

这一切都取决于

一个。数据访问的频率

b.数据访问的模式是什么

    分割文件 如果您需要偶尔访问数据,那么这个 2GB 日志 设计很好,如果不是,可以调整记录器以生成日志 周期性间隔/后一个逻辑可以将 2GB 文件拆分为所需的方式 较小的文件。这样就可以获取远程日志文件然后读取 日志数据,然后整理出所需的行更容易,因为文件 这里会减少读取的字节数。

    缓存 对于非常频繁的数据访问,为了更快的响应,维护缓存是一个很好的解决方案,正如你所说的那样,它有自己的瓶颈。缓存内存选择的大小和模式都取决于b。数据访问的模式是什么。缓存越大,响应越慢,应该是最优的。

    数据库 如果搜索模式在使用时是无序的/动态增长的,那么数据库将起作用。同样在这里它不会像小缓存那样提供更快的响应。

    数据库与支持查询类型的完美表组织+较小缓存层的组合将提供最佳结果。

【讨论】:

嗨@Praveen,感谢您提供的信息。如果我在这种情况下使用数据库,由于执行多个查询,再次出现性能瓶颈。每 5/10/20ms 读取一次数据。那么在这种情况下使用数据库可以吗? 我认为根据您的查询类型进行适当的数据库设计(表与适当字段的组合)将起作用。 :- 正如我之前所说的“数据访问是什么模式”在这里很重要,我认为取决于我们可以优化搜索查询的模式。如果模式是可预测的,那么我们可能会有一个小的缓存,这样从 db 中频繁提取的数据就会被最小化。我的意思是,例如,如果即将到来的 100 个查询将在特定的数据范围内,那么我们可能会在缓存中拥有该特定范围的数据(这就是我在上面 #4 中的意思)让我们知道任何更好的解决方案。 【参考方案3】:

这是我找到的解决方案:

    使用循环缓冲区(Boost lock free Buffers)来解析文件并保存行的结构化格式 使用单独的线程: 会不断解析文件并推送到无锁队列 会不断从缓冲区中读取数据,处理行,形成结构并推送到另一个队列 每当用户需要随机数据时,我都会根据时间将文件指针移动到特定行并只读特定行。 两个线程都有互斥等待机制,一旦达到预定义的缓冲区限制就会停止解析 用户可以随时获取数据,无需存储完整的文件内容。当框架被读取时,我将从队列中删除框架。所以文件大小无关紧要。填充缓冲区的并行线程允许不必每次都花时间读取文件。 如果我想移动到另一行,移动文件指针,擦除现有数据,重新启动线程。

注意: 现在唯一的问题是将文件指针移动到特定的行。 我需要逐行解析,直到达到目的。

如果存在将文件指针移动到所需行的任何解决方案,那将很有帮助。可以使用二进制搜索或任何有效的搜索算法,并会得到我想要的。

如果有人为上述新问题提供解决方案,我将不胜感激!

【讨论】:

以上是关于读取大文件(> 2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Java读写大文本文件(2GB以上)

Python 不读取整个文本文件

如何在 Ada 中读取大文件?

Go 读取大文件

读取大文本文件VB6中的行数

在客户端将大文件(> 2GB)压缩成 ZIP