2010-05-27 5 views
1

Я хочу заменить двоичный файл, если содержимое отличается.Можно ли сравнить двоичный файл в C#?

Поэтому мне нужно иметь возможность сравнить двоичный файл (без десериализации).

Возможно ли это?

Для сохранения файла я использовал двоичный форматтер.

+0

Вы должны уточнить свой вопрос: с чем вы сравниваете двоичный файл?Является ли это еще одним двоичным файлом или является экземпляром в памяти класса, который должен или не должен быть сериализован для файла? –

ответ

5

Да, вы можете сгенерировать байты MD5 или SHA1 для каждого набора данных файла, а затем сравнить их.

Пример кода (проверка ошибок для наглядности):

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

, если это всего лишь два файла, было бы лучше просто сравнить байты напрямую, так что вы могли бы выходить с первого раза раньше, но если вы вычисляете хэши, вы должны прочитать весь файл, который может быть очень дорогим. – luke

+0

Не обоим ли они читать весь файл? Тогда в чем смысл? Конечно, вычисление хэша будет полезно, если вы сравниваете один файл несколько раз, но это, похоже, не так. – 2010-05-27 18:28:26

+0

Вычисление хэшей на самом деле хуже - при сравнении байтов по байтам вы можете остановиться после первых нескольких байтов (если они отличаются). –

12

Да, это возможно.

Вам необходимо прочитать файл, чтобы сравнить его, если это то, о чем вы просите.

псевдо-код будет:

  • Открыть file1 и file2 в виде потоков.
  • На основании сравнения длина; если длина не равна, файлы не равны.
  • Прочитайте кусок каждого файла в буфер и сравните буферы. Повторяйте, пока не столкнетесь с различиями или не дойдете до конца файла.

Если вам нужно сравнить тот же файл с кучей других файлов, полезно вычислить хэш первого файла. Затем просто вычислите хэш каждого из других файлов и сравните хеши.

+1

Я бы немного изменил этот последний шаг: «повторяйте до тех пор, пока они не станут разными или не достигнут конец файла». Вы не хотели бы продолжать идти до конца, если первые байты разные. –

+2

Я подозреваю, что OP хочет определить, изменился ли класс на основе сериализованных версий. Я не думаю, что сравнение файлов будет работать, поскольку BinaryFormatter не гарантирует, что «тот же» класс будет иметь одни и те же байты. – 2010-05-27 18:26:53

+0

@ Нет, да, конечно; Я думал, что это было очевидно - исправил ответ сейчас :-) – driis

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

Затем проведите через него. Может быть медленным, если файл большой.

Может быть, вы должны искать файл MD5 хэш-алгоритма

0

Вы можете прочитать содержимое двоичного файла и сравнить байты, которые Вы получаете. Чтобы прочитать файл, вы можете либо использовать ReadAllBytes (если файл имеет достаточный размер и будет удобно помещать в память), либо вы можете использовать FileStream и читать фрагменты данных из обоих файлов.

Структура подхода с использованием буферов может выглядеть следующим образом:

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 
} 

Некоторые люди рекомендовали использовать хеши, но это не очень хорошая идея - если файлы одинаковы, вам нужно прочитать все данные из файла, поэтому вычисление хэшей не является более эффективным, чем просто чтение и сравнение всех данных. Однако, если файлы отличаются в первых байтах, вам нужно будет прочитать только первые несколько байтов (если сравнивать побайтовые байты)!

Хеши были бы полезны, если бы вы хотели сравнить несколько файлов (например, каждый из них).

0

Это функция для этого. Если кто-то еще не сможет обеспечить лучший способ сравнения байтовых массивов.

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; 
} 
Смежные вопросы