2008-10-31 3 views

Antwort

49

Das niedrige Niveau Weg:

from __future__ import with_statement 
with open(filename1) as f1: 
    with open(filename2) as f2: 
     if f1.read() == f2.read(): 
     ... 

Die hohe Art und Weise:

import filecmp 
if filecmp.cmp(filename1, filename2, shallow=False): 
    ... 
+9

ich Ihre filecmp.cmp Anruf korrigiert, denn ohne eine unechte oberflächliches Argument, es tut nicht, wonach die Frage fragt. – tzot

+2

Sie haben Recht. http://www.python.org/doc/2.5.2/lib/module-filecmp.html. Vielen Dank. –

+1

BTW, sollte man die Dateien im Binärmodus öffnen, um sicher zu sein, da die Dateien in Zeilentrennzeichen unterscheiden können. – newtover

3
 

f = open(filename1, "r").read() 
f2 = open(filename2,"r").read() 
print f == f2 

 
+5

"Nun, ich habe diese 8 GiB-Datei und diese 32 GiB-Datei, die ich vergleichen möchte ..." – tzot

22

Wenn Sie selbst grundlegende Effizienz gehen, werden Sie wahrscheinlich die Dateigröße überprüfen möchten zuerst :

if os.path.getsize(filename1) == os.path.getsize(filename2): 
    if open('filename1','r').read() == open('filename2','r').read(): 
    # Files are the same. 

Das spart Ihnen lesen Jede Zeile von zwei Dateien, die nicht einmal die gleiche Größe haben, kann also nicht identisch sein.

(Noch weiter als das, könnte man auf eine schnelle MD5sum jeder Datei rufen und diejenigen vergleichen, aber das ist nicht „in Python“, also werde ich hier aufhören.)

+2

Der Ansatz von md5sum wird langsamer mit nur 2 Dateien (Sie müssen immer noch die Datei lesen, um die Summe zu berechnen) Es lohnt sich nur wenn Sie nach Duplikaten unter mehreren Dateien suchen. – Brian

+0

@Brian: Sie gehen davon aus, dass das Lesen von md5sum nicht schneller ist als das von Python, und dass es keinen Overhead beim Lesen der gesamten Datei in die Python-Umgebung als String gibt! Versuchen Sie das mit 2GB-Dateien ... – Rich

+2

Es gibt keinen Grund zu erwarten, dass die Dateilesung von md5sum schneller ist als die von Python - IO ist ziemlich unabhängig von der Sprache. Das große Dateiproblem ist ein Grund, in Chunks zu iterieren (oder filecmp zu benutzen), nicht um md5 zu benutzen, wo du unnötig eine zusätzliche CPU-Strafe bezahlst. – Brian

1

Für größere Dateien könnten Sie Berechnen Sie einen MD5 oder SHA Hash der Dateien.

+3

Was also ist mit zwei 32 GiB Dateien, die sich nur im ersten Byte unterscheiden? Warum CPU-Zeit ausgeben und zu lange auf eine Antwort warten? – tzot

1

Ich würde einen Hash des Inhalts der Datei mit MD5 verwenden.

import hashlib 

def checksum(f): 
    md5 = hashlib.md5() 
    md5.update(open(f).read()) 
    return md5.hexdigest() 

def is_contents_same(f1, f2): 
    return checksum(f1) == checksum(f2) 

if not is_contents_same('foo.txt', 'bar.txt'): 
    print 'The contents are not the same!' 
5

Da ich die Antworten anderer nicht kommentieren kann, schreibe ich meine eigene.

Wenn Sie md5 verwenden, müssen Sie definitiv nicht nur md5.update (f.read()), da Sie zu viel Speicher verwenden.

def get_file_md5(f, chunk_size=8192): 
    h = hashlib.md5() 
    while True: 
     chunk = f.read(chunk_size) 
     if not chunk: 
      break 
     h.update(chunk) 
    return h.hexdigest() 
+1

Ich glaube, dass jede Hashing-Operation für die Zwecke dieser Frage übertrieben ist. direkter Stück-für-Stück-Vergleich ist schneller und geradliniger. – tzot

+0

Ich habe gerade den tatsächlichen Hashing-Teil aufgeräumt, den jemand vorgeschlagen hat. – user32141

+0

+1 Ich mag deine Version besser. Ich glaube auch nicht, dass die Verwendung eines Hashes zu viel ist. Es gibt wirklich keinen guten Grund, nicht, wenn alles, was Sie wissen wollen, ist, ob sie anders sind oder nicht. –

7

Dies ist eine funktionelle Dateivergleichsfunktion. Es gibt sofort False zurück, wenn die Dateien unterschiedliche Größen haben; sonst liest sie in 4KiB Blockgrößen und False zurückgibt sofort auf den ersten Unterschied:

from __future__ import with_statement 
import os 
import itertools, functools, operator 

def filecmp(filename1, filename2): 
    "Do the two files have exactly the same contents?" 
    with open(filename1, "rb") as fp1, open(filename2, "rb") as fp2: 
     if os.fstat(fp1.fileno()).st_size != os.fstat(fp2.fileno()).st_size: 
      return False # different sizes ∴ not equal 
     fp1_reader= functools.partial(fp1.read, 4096) 
     fp2_reader= functools.partial(fp2.read, 4096) 
     cmp_pairs= itertools.izip(iter(fp1_reader, ''), iter(fp2_reader, '')) 
     inequalities= itertools.starmap(operator.ne, cmp_pairs) 
     return not any(inequalities) 

if __name__ == "__main__": 
    import sys 
    print filecmp(sys.argv[1], sys.argv[2]) 

Nur eine andere Perspektive :)

0
from __future__ import with_statement 

filename1 = "G:\\test1.TXT" 

filename2 = "G:\\test2.TXT" 


with open(filename1) as f1: 

    with open(filename2) as f2: 

     file1list = f1.read().splitlines() 

     file2list = f2.read().splitlines() 

     list1length = len(file1list) 

     list2length = len(file2list) 

     if list1length == list2length: 

      for index in range(len(file1list)): 

       if file1list[index] == file2list[index]: 

        print file1list[index] + "==" + file2list[index] 

       else:     

        print file1list[index] + "!=" + file2list[index]+" Not-Equel" 

     else: 

      print "difference inthe size of the file and number of lines" 
Verwandte Themen