2010-05-27 3 views
1

Je souhaite remplacer un fichier binaire si le contenu est différent.Est-il possible de comparer un fichier binaire dans C#?

Je dois donc pouvoir comparer le fichier binaire (sans devoir le désérialiser).

Est-ce possible? J'ai utilisé le formateur binaire pour enregistrer le fichier.

+0

Vous devez clarifier votre question: avec quoi comparez-vous le fichier binaire?S'agit-il d'un autre fichier binaire ou s'agit-il d'une instance en mémoire d'une classe qui devrait ou ne devrait pas être sérialisée dans un fichier? –

Répondre

5

Oui, vous pouvez générer le hachage MD5 ou SHA1 pour chaque ensemble de données de fichier, puis les comparer.

Exemple de code (vérification d'erreurs pour plus de clarté):

public bool CompareFiles(string filePath1, string filePath2) 
{ 

    FileInfo info1 = new FileInfo(filePath1); 
    FileInfo info2 = new FileInfo(filePath2); 


    byte[] data1 = new byte[info1.Length] 
    byte[] data2 = new byte[info2.Length]; 

    FileStream fs1 = new FileStream(filePath1, FileMode.Open); 
    FileStream fs2 = new FileStream(filePath2, FileMode.Open); 

    fs1.Read(data1, 0, info1.Length); 
    fs2.Read(data2, 0, info2.Length); 

    fs1.Dispose(); 
    fs2.Dispose(); 

    SHA1 sha = new SHA1CryptoServiceProvider(); 

    byte[] hash1 = sha.ComputeHash(data1); 
    byte[] hash2 = sha.ComputeHash(data2); 

    // c# 2 or less: you need to compare the hash bytes yourself 

    // c# 3.5/4 
    bool result = hash1.SequenceEqual(hash2); 

    return result; 
} 
+0

si c'est juste deux fichiers, il serait préférable de simplement comparer les octets directement, de cette façon vous pouvez sortir tôt à la première différence, mais si vous calculez des hachages, vous devez lire le fichier entier qui peut être très coûteux. – luke

+0

Les deux ne lisent pas tout le fichier? Quel est le point alors? Bien sûr, le calcul du hachage sera utile si vous comparez un fichier plusieurs fois, mais cela ne semble pas être le cas. –

+0

Le calcul des hachages est en réalité pire - en comparant octet par octet, vous pouvez arrêter après les premiers octets (s'ils diffèrent). –

12

Oui, il est possible.

Vous avez besoin de lire le fichier afin de pouvoir les comparer, si c'est ce que vous demandez.

Le pseudo-code serait:

  • fichier1 Ouvrir et fichier2 sous forme de flux.
  • Commencez par comparer la longueur; si la longueur n'est pas égale, les fichiers ne sont pas égaux.
  • Lit un fragment de chaque fichier dans un tampon et compare les tampons. Répétez jusqu'à rencontrer des différences ou atteindre la fin du fichier.

Si vous avez besoin de comparer le même fichier à un tas d'autres fichiers, il peut être utile de calculer le hachage du premier fichier. Ensuite, il suffit de calculer le hachage de chacun des autres fichiers, et de comparer les hachages.

+1

Je modifierais légèrement cette dernière étape: "répéter jusqu'à ce qu'ils soient différents ou la fin du fichier atteinte" Vous ne voudriez pas continuer jusqu'à la fin si les premiers octets sont différents. –

+2

Je soupçonne que l'OP veut détecter si une classe a changé en fonction des versions sérialisées. Je ne pense pas que comparer les fichiers fonctionnera car BinaryFormatter ne garantit pas que la même classe aura exactement les mêmes octets. –

+0

@Neil, oui bien sûr; Je pensais que c'était évident - corrigé la réponse maintenant :-) – driis

0
byte[] myFile = File.ReadAllBytes(pathToFile); 

Parcourez ensuite la boucle. Peut être lent si le fichier est volumineux.

Peut-être que vous devriez chercher un algorithme de hachage MD5 fichier

0

Vous pouvez lire le contenu binaire du fichier et de comparer les octets que vous obtenez. Pour lire le fichier, vous pouvez soit utiliser ReadAllBytes (si le fichier est de taille raisonnable et s'adaptera à la mémoire confortablement) ou vous pouvez utiliser FileStream et lire des blocs de données à partir des deux fichiers.

La structure de l'approche en utilisant des tampons pourrait ressembler à ceci:

byte[] buffer1 = new byte[1024], buffer2 = new byte[1024]; 
using(var fs1 = new FileStream(firstFile, FileMode.Open, FileAccess.Read) 
using(var fs2 = new FileStream(secondFile, FileMode.Open, FileAccess.Read) 
{ 
    // Use: fs.Read(buffer1, 0, 1024) to repeatedly read 1kb of data 
    // from both fs1 and fs2 and compare the content in buffer1 and buffer2 
} 

Certaines personnes ont recommandé d'utiliser hash, mais ce n'est pas une bonne idée - si les fichiers sont les mêmes, vous aurez besoin de lire tout les données du fichier, le calcul des hachages n'est donc pas plus efficace que la simple lecture et la comparaison de toutes les données. Cependant, si les fichiers diffèrent dans les premiers octets, vous devrez lire seulement les premiers octets (si vous comparez octet par octet)!

Des hachages seraient utiles si vous vouliez comparer plusieurs fichiers (par exemple chacun avec chacun).

0

Voici une fonction pour le faire. À moins que quelqu'un d'autre ne puisse fournir un meilleur moyen de comparer les tableaux d'octets.

private static bool CompareFiles(string file1, string file2) 
{ 
    var fsFile1 = new System.IO.FileStream(file1, System.IO.FileMode.Open, System.IO.FileAccess.Read); 
    var fsFile2 = new System.IO.FileStream(file2, System.IO.FileMode.Open, System.IO.FileAccess.Read); 
    var md5 = new System.Security.Cryptography.MD5Cng(); 
    var md5File1 = md5.ComputeHash(fsFile1); 
    var md5File2 = md5.ComputeHash(fsFile2); 
    for (int i = 0; i < md5File1.Length; ++i) 
    { 
     if (md5File1[i] != md5File2[i]) 
      return false; 
    } 
    return true; 
} 
Questions connexes