比较两个文件并将缺少的值写入文件

时间:2011-11-30 01:14:28

标签: python file loops compare

当我尝试比较两个大文件时遇到问题。我要做的是从一个文件中取一行,搜索另一个文件的所有行以进行匹配,如果没有,则将该行写入另一个文件。我能够通过下面的简单示例重新创建问题:

file1.txt(内容

apple
banana
pear
peach
lime

file_old.txt(内容)

lime
apple
pear
peach

由于我在file1中寻找不在file_old中的行,我希望'banana'是输出文件中唯一显示的值。但是在输出文件“* fill_diff *”中,我显示:

apple
banana
banana

我的代码试图在文件中产生差异有什么问题?

def main():

    file_old = open(r'C:\Users\test\Desktop\file_old.txt', 'r+')
    file_new = open(r'C:\Users\test\Desktop\file1.txt', 'r+')
    file_diff = open(r'C:\Users\test\Desktop\file_diff.txt', 'w')

    for each_line in file_new: 
        for every_line in file_old:
            if each_line == every_line:
                break
            file_diff.write(each_line)

    file_old.close()
    file_new.close()
    file_diff.close()

main()

谢谢!

6 个答案:

答案 0 :(得分:4)

srgerg的回答将起作用。

但是,多次读取文件将具有非常大的运行时复杂性。因此,如果文件(虽然很大)足够小以适应内存,那么您可以考虑将file_old中的所有行放入数据结构中进行比较:

old_lines = set((line.strip() for line in open(r'C:\Users\test\Desktop\file_old.txt', 'r+')))
file_new = open(r'C:\Users\test\Desktop\file1.txt', 'r+')
file_diff = open(r'C:\Users\test\Desktop\file_diff.txt', 'w')

for line in file_new:
    if line.strip() not in old_lines:
        file_diff.write(line)
file_new.close()
file_diff.close()

希望这有帮助

答案 1 :(得分:2)

你可以先在O(n + n * log(n))中对两个文件进行排序,然后同时迭代这两个文件。

# sort file1 and file2 on disk or in memory
while len(file1) > 0 and len(file2) > 0:
    while file1[0] < file2[0]:
        diff.append(file1[0])
        file1 = file1[1:]
    while file1[0] > file2[0]:
        diff.append(file2[0])
        file2 = file2[1:]
    while file1[0] == file2[0]:
        file1 = file1[1:]
        file2 = file2[1:]
diff = diff + file1 + file2 # add the rest to the diff

答案 2 :(得分:1)

您需要在循环的每次迭代开始时返回file_old的开头。像这样:

for each_line in file_new:
    file_old.seek(0)
    for every_line in file_old:
        ...

此外,你最内层循环的逻辑似乎是错误的。我想你想要像

这样的东西
for each_line in file_new:
    file_old.seek(0)
    found = False
    for every_line in file_old:
        if each_line == every_line:
            found = True
            break

    if not found:
        file_diff.write(each_line)

答案 3 :(得分:1)

FWIW,difflib module是为这种用例而设计的。

如果您需要手动执行,Python的集合可以使其更容易:

file_diff = open(r'C:\Users\test\Desktop\file_diff.txt', 'w')
oldlines = set(open(r'C:\Users\test\Desktop\file_old.txt', 'r'))
for line in open(r'C:\Users\test\Desktop\file1.txt', 'r'):
    if line not in oldlines:
        file_diff.write(line)

答案 4 :(得分:1)

我怀疑你想要以任何顺序错过行

这是一个基于set()的快速而肮脏的实现:

def readfile(name):
    afile = open(name, 'r+')
    lines = set([l.strip() for l in afile])
    afile.close()
    return lines

def main():
    oldset = readfile(r'file_old.txt')
    newset = readfile(r'file1.txt')

    file_diff = open(r'file_diff.txt', 'w')

    for diff in (newset - oldset):
        file_diff.write(diff)

    file_diff.close()

main()

对于非常大的输入文件,这可能无法很好地扩展。

答案 5 :(得分:0)

如果您不能假设文件已排序,那么我会做这样的事情

def diffUnsorted(fn1, fn2) :
    return set([l.strip() for l in open(fn1) if l.strip() != ""]) - \
           set([l.strip() for l in open(fn2) if l.strip() != ""])

如果您要处理大文件,我会选择一个先对文件进行排序的解决方案,这样可以获得O(n)时间和O(1)空间(不包括排序......) )。