【问题标题】:Compare 2 files in Python在 Python 中比较 2 个文件
【发布时间】:2014-06-17 15:41:50
【问题描述】:

我正在尝试在 Python 中比较两个文件 A 和 C,但由于某种原因,双 for 循环似乎无法正常工作:

with open(locationA + filenameC,'r') as fileC, open(locationA + filenameA,'r') as fileA:
     for lineC in fileC:
         fieldC = lineC.split('#')
         for lineA in fileA:
             fieldA = lineA.split('#')
             print 'UserID Clicks' + fieldC[0]
             print 'UserID Activities' + fieldA[0]
             if (fieldC[0] == fieldA[0]) and (fieldC[2] == fieldA[2]):
                 print 'OK'

这里,似乎只比较了 C 的那一行,但对于其他行,“A 循环”似乎被忽略了。

谁能帮我解决这个问题?

【问题讨论】:

  • difflib 模块?
  • 一旦在外循环的第一次迭代中到达内循环中fileA 的末尾,指针就位于文件的末尾。后续对文件的迭代尝试不会做任何事情。
  • @jonrsharpe 关于您的问题的原因是正确的。您需要fileA.seek(0) 来重置您的句柄。
  • os.system('diff ' + filenameA + ' ' + filenameB)....好吧好吧,开个玩笑
  • 你真的想比较 A 中的每一行和 C 中的每一行吗?并且每次比较两次?

标签: python


【解决方案1】:

您的问题是,一旦您遍历 fileA 一次,您就需要再次更改指向文件开头的指针。 因此,您可能会从两个文件中创建两个列表,并根据需要对它们进行多次迭代。例如:

fileC_list = fileC.readlines()
fileA_list = fileA.readlines()
for lineC in fileC_list:
  # do something
  for lineA in fileA_list:
    # do somethins

【讨论】:

  • 最好在第一个 for 块的开头执行 fileA.seek(0)。
【解决方案2】:

嵌套循环的问题(从您当前问题的角度来看)恰恰是内部循环在外部循环的每次迭代中运行到完成。因此,通过显式调用 fileA 迭代器中的下一项来设置 lineA

with open(locationA + filenameC,'r') as fileC, open(locationA + filenameA,'r') as fileA:
     for lineC in fileC:
         fieldC = lineC.split('#')
         lineA = next(fileA)
         fieldA = lineA.split('#')
         print 'UserID Clicks' + fieldC[0]
         print 'UserID Activities' + fieldA[0]
         if (fieldC[0] == fieldA[0]) and (fieldC[2] == fieldA[2]):
             print 'OK'

一旦fileC 用尽,此逻辑将忽略来自fileA 的任何额外行,如果fileC 包含的行数多于FileA,则如果没有特殊检查,事情也可能会变得丑陋。

另一种方法可能是使用itertools.izip() 成对地从每个文件中收集行:

import itertools
with open(locationA + filenameC,'r') as fileC, open(locationA + filenameA,'r') as fileA:
for lineC, lineA in itertools.izip(fileC, fileA):
         fieldC = lineC.split('#')
         fieldA = lineA.split('#')
         print 'UserID Clicks' + fieldC[0]
         print 'UserID Activities' + fieldA[0]
         if (fieldC[0] == fieldA[0]) and (fieldC[2] == fieldA[2]):
             print 'OK'

我想不出使用其中一个而不是另一个的任何具体原因,但如果文件是任何大小的,请拒绝使用内置 zip() 函数而不是 itertools.izip() 的诱惑 - 前者返回一个列表,因此内存使用取决于文件大小,而后者是一个生成器,因此会根据需要创建值。

【讨论】:

    【解决方案3】:

    您正在将 FileA 中的所有行与 FileC 中的每一行进行比较。这意味着,对于文件 C 的每一行,您将读取整个文件 A,并且(如果您确实将指针移动到文件 A 的开头),您将一遍又一遍地读取它。

    同时阅读它们更容易,因为它们都有线条 如果它们相同,则做某事,从两者中读取

    如果不同,从最小的开始读取(A行

    并在剩余行数的情况下进行最后两个循环(两个循环,每个文件一个,因为您不知道哪一个用完了行)

    【讨论】:

      【解决方案4】:

      我知道这是一个旧线程,但是当有人在寻找比较 python 中的 2 个文本文件的解决方案时,它会出现在 google 上。

      这段代码对我有用。

      您可以更新代码并改用“with open”并根据需要进行微调,但它确实可以完成工作。

      # Ask the user to enter the names of files to compare
      fname1 = input("Enter the first filename (text1.txt): ")
      fname2 = input("Enter the second filename (text1.txt): ")
      
      # Open file for reading in text mode (default mode)
      f1 = open(fname1)
      f2 = open(fname2)
      
      # Print confirmation
      print("-----------------------------------")
      print("Comparing files ", " > " + fname1, " < " +fname2, sep='\n')
      print("-----------------------------------")
      
      # Read the first line from the files
      f1_line = f1.readline()
      f2_line = f2.readline()
      
      # Initialize counter for line number
      line_no = 1
      
      # Loop if either file1 or file2 has not reached EOF
      while f1_line != '' or f2_line != '':
      
          # Strip the leading whitespaces
          f1_line = f1_line.rstrip()
          f2_line = f2_line.rstrip()
      
          # Compare the lines from both file
          if f1_line != f2_line:
      
              # If a line does not exist on file2 then mark the output with + sign
              if f2_line == '' and f1_line != '':
                  print(">+", "Line-%d" % line_no, f1_line)
              # otherwise output the line on file1 and mark it with > sign
              elif f1_line != '':
                  print(">", "Line-%d" % line_no, f1_line)
      
              # If a line does not exist on file1 then mark the output with + sign
              if f1_line == '' and f2_line != '':
                  print("<+", "Line-%d" % line_no, f2_line)
              # otherwise output the line on file2 and mark it with < sign
              elif f2_line != '':
                  print("<", "Line-%d" %  line_no, f2_line)
      
              # Print a blank line
              print()
      
          #Read the next line from the file
          f1_line = f1.readline()
          f2_line = f2.readline()
      
      
          #Increment line counter
          line_no += 1
      
      # Close the files
      f1.close()
      f2.close()
      

      【讨论】: