Если вы d̲o̲ решите, что вам действительно нужно полное побайтное сравнение (см. Другие ответы для обсуждения хэширования), тогда однострочное решение:
bool filesAreEqual = File.ReadAllBytes(path1).SequenceEqual(File.ReadAllBytes(path2));
В отличие от некоторых других опубликованных ответов, это работает корректно для любого типа файла: двоичного, текстового, мультимедийного, исполняемого и т. Д., Но в качестве полного двоичного сравнения , файлы, которые отличаются только"неважными" способами (такими как BOM , конец строки , кодировка символов , медиа-метаданные, пробелы, отступы, комментарии исходного кода и т. д.) всегда будут считаться не равными .
Этот код полностью загружает оба файла в память, поэтому его не следует использовать для сравнения гигантских файлов. Помимо этого соображения, полная загрузка на самом деле не штраф; фактически это может быть оптимальное решение .NET для размеров файлов, которые, как ожидается, будут меньше 85K , поскольку небольшие выделения в .NET
очень дешевы, а приведенный выше код максимально делегирует производительность и оптимизацию файлов CLR
/ BCL
.
Кроме того, для таких рабочих сценариев беспокойство по поводу производительности побайтного сравнения с помощью LINQ
перечислителей (как показано здесь) не имеет значения, поскольку попадание на диск a̲t̲ a̲l̲l̲ для файла I / O на несколько порядков превзойдет преимущества различных альтернатив сравнения памяти. Например, хотя SequenceEqual
действительно фактически дает нам «оптимизацию» отказа от первого несоответствия , это вряд ли имеет значение после того, как вы уже извлекли содержимое файлов, каждый из которых был полностью необходим чтобы подтвердить совпадение ..
С другой стороны, приведенный выше код не включает , включающий готовый прерывание для файлов различного размера , которые могут обеспечить ощутимую (возможно, измеримую) производительность разница. Это реально, потому что, хотя длина файла доступна в структуре WIN32_FILE_ATTRIBUTE_DATA
(которая в любом случае должна быть извлечена первой для любого доступа к файлу), продолжение доступа к содержимому файла требует совершенно другой выборки, которую потенциально можно избежать. Если вы обеспокоены этим, решение становится двумя строками:
// slight optimization over the code shown above
bool filesAreEqual = new FileInfo(path1).Length == new FileInfo(path2).Length &&
File.ReadAllBytes(path1).SequenceEqual(File.ReadAllBytes(path2));
Вы также можете расширить это, чтобы избежать вторичных выборок, если оба (эквивалентные) значения Length
оба найдены равными нулю (не показаны), и / или чтобы избежать построения каждого FileInfo
дважды (также не показано).