所以我有这些巨大的文本文件,每行填充一个逗号分隔的记录。我需要一种逐行处理文件的方法,删除符合特定条件的行。一些删除很容易,例如其中一个字段小于一定长度。最难的标准是这些行都有时间戳。除了时间戳之外,许多记录是相同的,我必须删除所有记录,但是一个记录是相同的,并且在15秒内彼此相同。
所以我想知道其他人是否可以为此提出最好的方法。我确实想出了一个用Java完成任务的小程序,使用JodaTime作为时间戳的东西,这让它变得非常简单。但是,我编写程序的最初方式是遇到OutofMemory堆空间错误。我稍微重构了一下代码,但大多数情况下看起来还不错,但我仍然认为它有一些内存问题,因为程序似乎偶尔会被挂起。这似乎只是花了太长时间。我不确定这是一个内存泄漏问题,一个糟糕的编码问题,还是完全不同的东西。是的,我尝试过显着增加堆大小,但仍然存在问题。
我会说该程序需要使用Perl或Java。我也许能够使python脚本工作,但我对python并不太熟悉。正如我所说,由于JodaTime库,时间戳的内容对我来说最简单(对我而言)。我不确定如何完成Perl中的时间戳。但是我要学习并使用最好的方法。
我还会添加正在阅读的文件大小各不相同,但有些大文件大约有100Mb,有130万条记录。
我的代码基本上读入所有记录并将它们放入Hashmap中,其中键是来自类似记录将共享的记录的数据的特定子集。所以记录的一个子集不包括不同的时间戳。这样,您最终会得到一些具有相同数据但在不同时间发生的记录。 (完全相同,减去时间戳)。
然后,每个键的值是一组具有相同数据子集的所有记录。然后我简单地遍历Hashmap,获取每个集合并迭代它。我拿第一张唱片并将其时间与剩下的所有时间进行比较,看看它们是否在15秒内。如果是,则删除记录。完成该设置后,它会写入文件,直到所有记录都已完成。希望这是有道理的。
这很有效,但显然我正在做的事情是内存过于密集。任何人都有更好的方法去做吗?或者,我在Perl中可以这样做的方式实际上是好的,因为尝试将Java程序插入到当前实现中已经引起了许多其他问题。虽然这或许只是因为我的记忆问题和编码不好。
最后,我不是要求别人为我编写程序。伪代码很好。虽然如果你有Perl的想法,我可以使用更多的细节。我不确定如何在Perl中做的主要是时间比较的东西。我看了一下Perl库,但没有看到像JodaTime这样的东西(尽管我看起来并不多)。任何想法或建议表示赞赏。谢谢。
答案 0 :(得分:4)
读取所有行并不理想,因为您需要将整个行存储在内存中。
相反,您可以逐行阅读,写出您想要保留的记录。您可以保留先前已经击中的行的缓存,限制在当前程序的15秒内。在非常粗略的伪代码中,对于你读过的每一行:
var line = ReadLine()
DiscardAnythingInCacheOlderThan(line.Date().Minus(15 seconds);
if (!cache.ContainsSomethingMatchingCriteria()) {
// it's a line we want to keep
WriteLine(line);
}
UpdateCache(line); // make sure we store this line so we don't write it out again.
正如所指出的,这假设线条按时间戳顺序排列。如果它们不是,那么我只是使用UNIX sort
来实现它们,因为它会非常愉快地处理非常大的文件。
答案 1 :(得分:0)
您可能会读取文件并输出要删除的行号(要在单独的通道中进行排序和使用。)您的哈希映射可能只包含所需的最小数据加上行号。如果所需数据与行大小相比较小,则可以节省大量内存。