Outils pour utilisateurs

Outils du site


comparefichiers

Test de comparaison du contenu de 2 fichiers

Objectif

Dire si 2 fichiers ont le même contenu, sans tenir compte des dates ni des autres propriétés (à part la longueur, bien entendu).

Solution proposée

Faire une lecture binaire du contenu des 2 fichiers pour les comparer.

Cette lecture/comparaison est progressive, et permet de s'arrêter au 1er écart trouvé.

Il faut, bien sûr, gérer toutes les erreurs possibles: fichier n'existe pas, ou erreur d'ouverture, de lecture ou de fermeture.

Code proposé

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import os
 
def compfichiers(nfc1, nfc2, lgbuf=32*1024):
    """Compare les 2 fichiers et renvoie True seulement s'ils ont un contenu identique"""
    f1 = f2 = None
    result = False
    try:
        if os.path.getsize(nfc1) == os.path.getsize(nfc2):
            f1 = open(nfc1, "rb")
            f2 = open(nfc2, "rb")
            while True:
                buf1 = f1.read(lgbuf)
                if len(buf1) == 0:
                    result = True
                    break
                buf2 = f2.read(lgbuf)
                if buf1 != buf2:
                    break
            f1.close()
            f2.close()
    except:
        if f1 != None: f1.close()
        if f2 != None: f2.close()
        raise IOError
    return result


Les 2 arguments nfc1 et nfc2 doivent être des noms de fichiers complets avec leur chemin.

Je n'ai pas essayé, mais a priori, le code devrait être multi-plateforme.

Cette fonction renvoie 3 résultats possibles:

  • True si les contenus sont identiques
  • False s'ils ne le sont pas
  • Une exception si une erreur est intervenue (fichier inconnu, erreur d'ouverture, de lecture, de fermeture)


Voilà comment on y fait appel dans ces 3 cas:

if __name__ == "__main__":
 
    import time
 
    # 1er cas: les 2 fichiers sont identiques 
    nf1 = r"C:\Python25\DLLs\tk84.dll"
    nf2 = r"C:\Python25\DLLs\tk84_idem.dll"
 
    try:
        t = time.clock()
        result = compfichiers(nf1, nf2)
        t = time.clock()-t
        print u"Résultat:", result, "%.3f s" % t
    except:
        t = time.clock()-t
        print u"Résultat: Erreur", "%.3f s" % t
 
 
    # 2ème cas: les 2 fichiers sont différents 
    nf1 = r"C:\Python25\DLLs\tk84.dll"
    nf2 = r"C:\Python25\DLLs\unicodedata.pyd"
    try:
        t = time.clock()
        result = compfichiers(nf1, nf2)
        t = time.clock()-t
        print u"Résultat:", result, "%.3f s" % t
    except:
        t = time.clock()-t
        print u"Résultat: Erreur", "%.3f s" % t
 
    # 3ème cas: le second fichier n'existe pas
    nf1 = r"C:\Python25\DLLs\tk84.dll"
    nf2 = r"C:\Python25\DLLs\cefichiernexistepas.$$$"
    try:
        t = time.clock()
        result = compfichiers(nf1, nf2)
        t = time.clock()-t
        print u"Résultat:", result, "%.3f s" % t
    except:
        t = time.clock()-t
        print u"Résultat: Erreur", "%.3f s" % t


Ce qui donne bien les résultas attendus (avec la durée en secondes):

Résultat: True 0.004 s
Résultat: False 0.000 s
Résultat: Erreur 0.000 s


Le résultat est renvoyé très rapidement, le plus lent étant la comparaison entre 2 fichiers identiques (c'est normal: il faut tout lire!). Mais ici, on a obtenu le résultat “True” en 4 millisecondes avec 2 fichiers identiques d'1Mo chacun.

Avec des fichiers beaucoup plus gros, ça se gâte un peu: avec 4.24Go (c'est l'image iso d'un DVD linux), la réponse demande 3 minutes.

Les solutions passant par la comparaison de résultats de hashage ne sont pas plus rapides (il faut tout de même lire les 2 fichiers pour cela!). De plus, l'égalité des empreintes hash des 2 fichiers ne donne pas la garantie absolue que les 2 contenus sont identiques.


Amusez-vous bien!

comparefichiers.txt · Dernière modification: 2010/04/11 07:39 de tyrtamos

Outils de la page