Feedback

C# - Binärvergleich zweier Dateien

Veröffentlicht von am 1/22/2010
(2 Bewertungen)
Das Snippet vergleicht 2 auf der Platte liegende Dateien binär miteinander. Es gibt lediglich eine statische Methode, die das Vergleichsergebnis als bool zurückliefert.
        /// <summary>
        /// Methode, die einen Binärvergleich von 2 Dateien macht und
        /// das Vergleichsergebnis zurückliefert.
        /// </summary>
        /// <param name="p_FileA">Voll qualifizierte Pfadangabe zur ersten Datei.</param>
        /// <param name="p_FileB">Voll qualifizierte Pfadangabe zur zweiten Datei.</param>
        /// <returns>True, wenn die Dateien binär gleich sind, andernfalls False.</returns>
        private static bool FileDiffer(string p_FileA, string p_FileB)
        {
            bool retVal = true;
            FileInfo infoA = null;
            FileInfo infoB = null;
            byte[] bufferA = new byte[128];
            byte[] bufferB = new byte[128];
            int bufferRead = 0;

            // Die Dateien überprüfen
            if (!File.Exists(p_FileA))
            {
                throw new ArgumentException(String.Format("Die Datei '{0}' konnte nicht gefunden werden", p_FileA), "p_FileA");
            }
            if (!File.Exists(p_FileB))
            {
                throw new ArgumentException(String.Format("Die Datei '{0}' konnte nicht gefunden werden", p_FileB), "p_FileB");
            }

            // Dateiinfo wegen der Dateigröße erzeugen
            infoA = new FileInfo(p_FileA);
            infoB = new FileInfo(p_FileB);

            // Wenn die Dateigröße gleich ist, dann einen Vergleich anstossen
            if (infoA.Length == infoB.Length)
            {
                // Binärvergleich
                using (BinaryReader readerA = new BinaryReader(File.OpenRead(p_FileA)))
                {
                    using (BinaryReader readerB = new BinaryReader(File.OpenRead(p_FileB)))
                    {
                        // Dateistream blockweise über Puffer einlesen
                        while ((bufferRead = readerA.Read(bufferA, 0, bufferA.Length)) > 0)
                        {
                            // Dateigrößen sind gleich, deshalb kann hier
                            // ungeprüft auch von der 2. Datei eingelesen werden
                            readerB.Read(bufferB, 0, bufferB.Length);

                            // Bytevergleich innerhalb des Puffers
                            for (int i = 0; i < Math.Min(bufferA.Length, bufferRead); i++)
                            {
                                if (bufferA[i] != bufferB[i])
                                {
                                    retVal = false;
                                    break;
                                }
                            }

                            // Wenn Vergleich bereits fehlgeschlagen, dann hier schon abbruch
                            if (!retVal)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                // Die Dateigröße ist schon unterschiedlich
                retVal = false;
            }

            return retVal;
        }
Abgelegt unter binary, binär, compare, vergleich, diff.

1 Kommentare zum Snippet

DBrueckmann schrieb am 2/13/2020:
Hallo ich habe das mal ein klein bisschen umgearbeitet - statt byteweisem Vergleich mit SequenceEqual.

Hier die statische Klasse:

using System.IO;
using System.Linq;

namespace DateiVerwaltung
{
public static class DateiService
{
//https://dotnet-snippets.de/snippet/binaervergleich-zweier-dateien/1322
/// <summary>
/// Methode, die einen Binärvergleich von 2 Dateien macht und
/// das Vergleichsergebnis zurückliefert.
/// </summary>
/// <param name="p_FileA">Voll qualifizierte Pfadangabe zur ersten Datei.</param>
/// <param name="p_FileB">Voll qualifizierte Pfadangabe zur zweiten Datei.</param>
/// <returns>True, wenn die Dateien binär gleich sind, andernfalls False.</returns>
public static bool Vergleich(string p_FileA, string p_FileB, out string fehlerInfo)
{
const int pufferGroesse = 128;

FileInfo infoA = null;
FileInfo infoB = null;
byte[] bufferA = new byte[pufferGroesse];
byte[] bufferB = new byte[pufferGroesse];
int bufferRead = 0;

// Die Dateien überprüfen
if (!File.Exists(p_FileA))
{
fehlerInfo = $"Die Datei '{p_FileA}' konnte nicht gefunden werden!";
return false;
}
if (!File.Exists(p_FileB))
{
fehlerInfo = $"Die Datei '{p_FileB}' konnte nicht gefunden werden!";
return false;
}

// Dateiinfo wegen der Dateigröße erzeugen
infoA = new FileInfo(p_FileA);
infoB = new FileInfo(p_FileB);

// nur wenn die Dateigröße gleich ist, dann einen Vergleich anstossen
if (infoA.Length != infoB.Length)
{
fehlerInfo = $"Die Dateien '{p_FileA}' und '{p_FileB}' sind ungleich lang!";
return false;
}
else
{
// Fehlerinfo schon hier festlegen
fehlerInfo = $"Die Dateien '{p_FileA}' und '{p_FileB}' sind ungleich!";
// Binärvergleich
using (BinaryReader readerA = new BinaryReader(File.OpenRead(p_FileA)))
{
using (BinaryReader readerB = new BinaryReader(File.OpenRead(p_FileB)))
{
// Dateistream blockweise über Puffer einlesen
while ((bufferRead = readerA.Read(bufferA, 0, pufferGroesse)) > 0)
{
// Dateigrößen sind gleich, deshalb kann hier
// ungeprüft auch von der 2. Datei eingelesen werden
readerB.Read(bufferB, 0, pufferGroesse);
if (bufferRead == pufferGroesse)
{
if (!bufferA.SequenceEqual(bufferB))
{
return false;
}
}
else
{
// am Ende sind es wahrscheinlich ein paar Bytes weniger
if (!bufferA.Take(bufferRead).ToArray().SequenceEqual(bufferB.Take(bufferRead).ToArray()))
{
return false;
}
}
}
}
}
// kein Fehler
fehlerInfo = "";
return true;
}
}
}
}


und hier der Unittest:

using DateiVerwaltung;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;

namespace UnitTestTechniken.Dateien
{
[TestClass]
public class TestDateiVergleich
{
private const string DateiText = @"
Er soll alles wieder besser machen und die am Boden liegende
Organisation aufrichten. Er war ja früher mal erfolgreich. Das ist zwar
schon etwas her – aber er hat in der Zwischenzeit andernorts genug
Erfahrungen gesammelt. Manchen erscheint er jetzt als Lichtgestalt,
geradezu als Erlöser, mit der man zu vergangener Größe zurückkehren
wird.
";
private const string verzeichnis = @"C:\Temp\DateiVergleich\";
private const string datei1 = verzeichnis+"Datei1.txt";
private const string dateiUngleich = verzeichnis + "DateiUngleich.txt";
private const string dateiGleich = verzeichnis + "DateiGleich.txt";

private static void Schreibe(string dateiName, string text)
{
using (StreamWriter file = new StreamWriter(dateiName, false, System.Text.Encoding.UTF8))
{
file.Write(text);
file.Close();
}
}
[TestMethod]
public void DateienErzeugen()
{
if (Directory.Exists(verzeichnis))
{
// aufräumen
Directory.Delete(verzeichnis, true);
}
Directory.CreateDirectory(verzeichnis);
Schreibe(datei1, DateiText);
Schreibe(dateiGleich, DateiText);
Schreibe(dateiUngleich, DateiText.Replace("man","xxx")); // die Dateilängen bleiben gleich
}
[TestMethod]
public void DateiGleich()
{
Assert.IsTrue(DateiService.Vergleich(datei1, dateiGleich, out string fehlerinfo));
}
[TestMethod]
public void DateiUngleich()
{
Assert.IsFalse(DateiService.Vergleich(datei1, dateiUngleich, out string fehlerinfo));
Assert.AreEqual(fehlerinfo, $"Die Dateien '{datei1}' und '{dateiUngleich}' sind ungleich!");
}
}
}

 

Logge dich ein, um hier zu kommentieren!