解析不是二进制文件(Python或C ++)的大文件

时间:2014-01-16 19:02:12

标签: python c++ parsing ascii bigdata

作为免责声明,我不是计算机科学家,但我一直在阅读有关高效文件i / o的所有内容,试图解决我正在研究的项目的这个方面。

我有一个非常大(10 - 100 GB)的逗号分隔值日志文件,我需要解析它。第一个值将其标记为“A”或“B”;对于每个“A”行,我需要检查它之前的行和它之后的行,如果它之前或之后的行符合标准,我想将它存储在内存中或将其写入文件。线条的大小不均匀。

这是我的具体问题:我似乎无法在非二进制文件中找到高效方法。使用二进制文件,我只需迭代文件一次,然后通过逻辑检查来回回放。我已经调查了内存映射,但似乎是为二进制文件构建的;我目前的代码是Pythonic,需要数周才能运行[见免责声明]。

我的另一个问题是 - 在这里如何轻易地引用并行性来帮助它?我有一个概念 - 如何 - 一次将文件映射出三行并将每个块发送到每个节点[第1,2,3行转到一个节点;第3,4,5行转到另一个......],但我不知道如何实现这个。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

只需读取循环中的行。跟踪内存中的上一行并在需要时进行检查。

伪代码:

for each line:
    previousLine := currentLine
    read currentLine from file
    do processing...

这是有效的,假设您已经将每一行都读入内存,并且如果您使用适当的缓冲方案来读取文件(一次将大块读取到内存中)。

我不认为并行性会对这种情况有所帮助。如果写得正确,程序的瓶颈应该是磁盘I / O,并且多个线程/进程无法比单个线程更快地从磁盘读取。并行性只能改善CPU限制的问题。

对于它的价值,您可以在ASCII文件中“寻找”与二进制文件相同的方式。您只需在每次开始读取行时跟踪文件偏移量,并存储该偏移量,以便您知道以后要在何处寻找。根据实现的方式,这将永远不会比上面的更好,有时甚至更糟(你希望文件数据在内存中缓冲,以便“搜索”是一个内存操作,而不是磁盘操作;你肯定想要按顺序读取文件内容以最大限度地提高缓存优势。)

答案 1 :(得分:1)

这是第一关。假设格式正确的文本行。

from itertools import chain

with open('your-file') as f:
    prev_line = None
    cur_line = f.readline()
    for next_line in chain(f, [None]):
        pieces = cur_line.split(',')
        if pieces[0] == 'A':
            check_against_criterion_if_not_none(prev_line)
            check_against_criterion_if_not_none(next_line)
        prev_line, cur_line = cur_line, next_line

一个漂亮的技巧是使用itertools.chain在文件末尾添加额外的'None',以便代码正确地检查文件的最后一行与第二行到最后一行。