【问题标题】:Quickly find differences between two large text files快速查找两个大文本文件之间的差异
【发布时间】:2011-04-02 10:34:56
【问题描述】:

我有两个 3GB 的文本文件,每个文件大约有 8000 万行。它们共享 99.9% 的相同行(文件 A 有 60,000 行,文件 B 有 80,000 行)。

如何在两个文件中快速找到这些独特的行?是否有任何现成的命令行工具可以做到这一点?我正在使用 Python,但我想找到一种有效的 Pythonic 方法来加载文件并进行比较是不太可能的。

欢迎提出任何建议。

【问题讨论】:

  • 你是说99.9%的文件是相同的,还是说99.9%的是相同的(即同一行重复)?
  • 你关心行的顺序吗? B 的所有行是否与 A 的顺序相同?可以重新排序,删除行吗?是否存在计数重要的重复行(A 有 n 次,B 有 n-b 次-> 差异是 b*line)
  • 如果您询问“即用型命令行工具”,您可能需要指定操作系统。在大多数情况下,“diff”要么是原生的,要么是移植的。不过,我不能确定你想从你的问题中得到什么:也许在 Linux 上: sort --unique uniq1;排序 --unique uniq1; diff uniq[12].
  • 平均每行多少字节?
  • @bstpierre,确切地说,两个文件中 99.9% 的行是相同的,但唯一的行随机分布在两个文件中。

标签: python file text diff compare


【解决方案1】:

如果订单很重要,请尝试comm 实用程序。如果顺序无关紧要,sort file1 file2 | uniq -u

【讨论】:

  • 排序两个3G文件会比diff快吗?
  • @bstpierre:diff 实现通常是二次的,而排序通常是 n log n 在平均情况下(快速排序)。
【解决方案2】:

我认为这是最快的方法(无论是使用 Python 还是其他语言,IMO 都不应该太重要)。

注意事项:

1.我只存储每行的哈希以节省空间(如果可能发生分页,还可以节省时间)

2.由于以上原因,我只打印出行号;如果你需要实际的行,你只需要再次读取文件

3.我假设散列函数不会导致冲突。这几乎是肯定的,但并不完全确定。

4.我导入hashlib是因为内置的hash()函数太短,无法避免冲突。

import sys
import hashlib

file = []
lines = []
for i in range(2):
    # open the files named in the command line
    file.append(open(sys.argv[1+i], 'r'))
    # stores the hash value and the line number for each line in file i
    lines.append({})
    # assuming you like counting lines starting with 1
    counter = 1
    while 1:
        # assuming default encoding is sufficient to handle the input file
        line = file[i].readline().encode()
        if not line: break
        hashcode = hashlib.sha512(line).hexdigest()
        lines[i][hashcode] = sys.argv[1+i]+': '+str(counter)
        counter += 1
unique0 = lines[0].keys() - lines[1].keys()
unique1 = lines[1].keys() - lines[0].keys()
result = [lines[0][x] for x in unique0] + [lines[1][x] for x in unique1]

【讨论】:

  • 对我来说看起来不错的答案,我只建议在阅读时保存每行的查找位置以快速恢复它们以获得结果。
【解决方案3】:

如果有 60,000 或 80,000 行唯一行,您可以为每个唯一行创建一个字典,将其映射到一个数字。 mydict["hello world"] => 1 等。如果您的平均行大约为 40-80 个字符,那么这将在 10 MB 内存附近。

然后读取每个文件,通过字典将其转换为数字数组。这些将很容易放入内存中(2 个 8 字节 * 3GB / 60k 行的文件小于 1 MB 的内存)。然后区分列表。您可以invert the dictionary 并使用它打印出不同行的文本。

编辑:

作为对您的评论的回应,这里有一个示例脚本,它在从文件中读取时为唯一的行分配数字。

#!/usr/bin/python

class Reader:

    def __init__(self, file):
        self.count = 0
        self.dict = {}
        self.file = file

    def readline(self):
        line = self.file.readline()
        if not line:
            return None
        if self.dict.has_key(line):
            return self.dict[line]
        else:
            self.count = self.count + 1
            self.dict[line] = self.count
            return self.count

if __name__ == '__main__':
    print "Type Ctrl-D to quit."
    import sys
    r = Reader(sys.stdin)
    result = 'ignore'
    while result:
        result = r.readline()
        print result

【讨论】:

  • @Harold L,我很困惑。在知道两个文件中包含哪些行之前,如何将 60,000 或 80,000 个唯一行映射到字典。
  • 您可以在阅读文件时构建字典。我将为上面的辅助函数添加代码。
  • dict.keys() 有 3 GB?我不相信您只能使用 seff.dict[line] 保存哈希,但它会将整行保存在键 + 哈希中。
  • @Tony Veijalainen,是的,字典会保存整行,但它只会保存每行一次。所以这种技术在这里很有效,只是因为 Jack 有很多重复的行:3GB 可能是 1 亿行文本,但只有 80,000 行唯一的行将存储在字典的键集中。
  • “两个文件中没有重复的行”。请参阅海报对他的帖子的评论以回答我。也许我听不懂他的英语。
【解决方案4】:

如果我理解正确,您希望这些文件的行没有重复。这样就可以了:

uniqA = set(open('fileA', 'r'))

【讨论】:

    【解决方案5】:

    Python 有 difflib,它声称与其他 diff 实用程序相当有竞争力,请参阅: http://docs.python.org/library/difflib.html

    【讨论】:

    • 这个库可以处理 3gb 的文本文件吗?!即使是好的数据库也很难完成这类任务......他们需要索引和其他优化才能在合理的时间内获得结果。
    • 因为线条是随机排列的,不需要寻找线条的变化,可能不是最好的方法。如果两个文件是同一个文件的版本,这将是合适的(因为它们之间的行高度相似)。
    猜你喜欢
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多