Inkrementelles Backup

T

TimWegener

Hallo Zusammen,

ich möchte gerne eine Anwendung schreiben, mit der ich Daten inkrementell sichern kann. Hierbei würde ich gerne die Dateien und Ordner 1:1 von der Quelle zum Ziel kopieren.
Um das Ganze zu optimieren, sollen aber nur neuere bzw. veränderte Dateien kopiert werden. Zum Abschluss sollen dann alle Dateien im Ziel gelöscht werden, die in der Quelle nicht mehr vorhanden sind.

Gibt es möglicherweise eine Funktion, die nach diesem Schema arbeitet? Die Konsole beispielsweise kennt den Befehl „robocopy“ (ab Vista glaube ich), der genau dies tut.

Wenn es einen solchen Befehl nicht gibt, würde ich mich freuen, wenn mir jemand seine Ideen für den Ablauf eines solchen Programms schreiben könnte.

Danke im Voraus… :)
 
Ich kenne jetzt keine spezielle .Net-Funktion, die dir besonders Arbeit abnehmen würde.
Aber du kannst dir Robocopy.exe bei Microsoft runterladen, dann hast du das Programm auch für Nicht-Vista (d.h. WinXP):
Lade dir Windows Server 2003 Resource Kit Tools herunter, suche dann im Download nach robocopy.exe und lösche die anderen Dateien :)
(kleine Anmerkung: Microsoft hat inzwischen eine GUI für Robocopy herausgegeben)
 
Erst mal Danke für die Antwort. :)

Also was für mich nicht in Frage kommt, ein fertiges Tool zu nehmen. Das wär mir zu einfach. ;)

robocopy herunterladen und dann evtl. über C# zu benutzen wäre eine Option, jedoch nicht unbedingt das, was ich mir vorgestellt hatte.

Grundsätzlich wäre es ja möglich den Quellordner rekursiv zu kopieren und die Dateien die schon vorhanden sind über einen MD5-Hash zu vergleichen.

Nur die Frage, ob da MD5 die richtige Wahl ist? (Performance bzw. erkennen aller Änderungen)
Und wie lösche ich die Dateien im Ziel, die in der Quelle nicht mehr vorhanden sind?
 
Die Klasse System.IO.File ist mir durchaus bekannt, nur bietet diese meines Wissens und meiner Recherche nach keine Funktion um inkrementell zu kopieren.
Ich lasse mich natürlich gerne eines Besseren belehren ;)

Hier mal der Code den ich mir mal so zusammengebastelt habe (hab leider die Quellen für das rekursive kopieren und den MD5-Hash gerade nicht parat)

Code:
private void CopyDirectoryWithIncludedFiles(string dirCopySource, string dirCopyTarget)
        {
// alle Unterverzeichnisse des aktuellen Verzeichnisses ermitteln
                string[] subDirectories = Directory.GetDirectories(dirCopySource);

                // Zielpfad erzeugen
                StringBuilder newTargetPath = new StringBuilder();
                {
                    newTargetPath.Append(dirCopyTarget);
                    newTargetPath.Append(dirCopySource.Substring(dirCopySource.LastIndexOf(@"\")));
                }

                // wenn aktueller Ordner nicht existiert -> ersstellen
                if (!Directory.Exists(newTargetPath.ToString()))
                    Directory.CreateDirectory(newTargetPath.ToString());


                // Unterverzeichnise durchlaufen und Funktion mit dazu gehörigen Zielpfad erneut aufrufen (Rekursion)
                foreach (string subDirectory in subDirectories)
                {
                    string newDirectoryPath = subDirectory;

                    // wenn ''/'' an letzter Stelle dann entfernen
                    if (newDirectoryPath.LastIndexOf(@"\") == (newDirectoryPath.Length - 1))
                        newDirectoryPath = newDirectoryPath.Substring(0, newDirectoryPath.Length - 1);

                    // rekursiever Aufruf
                    CopyDirectoryWithIncludedFiles(newDirectoryPath, newTargetPath.ToString());
                }


                // alle enthaltenden Dateien des aktuellen Verzeichnisses ermitteln
                string[] fileNames = Directory.GetFiles(dirCopySource);
                foreach (string fileSource in fileNames)
                {
                    // Zielpfad + Dateiname
                    StringBuilder fileTarget = new StringBuilder();
                    {
                        fileTarget.Append(newTargetPath);
                        fileTarget.Append(fileSource.Substring(fileSource.LastIndexOf(@"\")));
                    }

                    // Datei kopieren, wenn schon vorhanden und nicht der ursprünglichen Datei entsprechen überschreiben
                    if (File.Exists(fileTarget.ToString()))
                    {
                        if (Datei2MD5(fileSource, fileTarget.ToString()) == false)
                        {
                                File.Copy(fileSource, fileTarget.ToString(), true);
                        }
                    }
                    else
                    {
                            File.Copy(fileSource, fileTarget.ToString(), false);
                    }

                }
            }
}


private bool Datei2MD5(string Dateipfad1, string Dateipfad2)
        {
            try
            {
                //Datei einlesen
                System.IO.FileStream FileCheck = System.IO.File.OpenRead(Dateipfad1);
                // MD5-Hash aus dem Byte-Array berechnen
                System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] md5Hash = md5.ComputeHash(FileCheck);
                FileCheck.Close();

                //in string wandeln
                string Berechnet1 = BitConverter.ToString(md5Hash).Replace("-", "").ToLower();

                //Datei einlesen
                FileCheck = System.IO.File.OpenRead(Dateipfad2);
                // MD5-Hash aus dem Byte-Array berechnen
                md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                md5Hash = md5.ComputeHash(FileCheck);
                FileCheck.Close();

                //in string wandeln
                string Berechnet2 = BitConverter.ToString(md5Hash).Replace("-", "").ToLower();

                // Vergleichen
                if (Berechnet1 == Berechnet2)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            { return false; }
        }

Probleme:

Wie schon gesagt MD5-Hash, da recht langsam und nicht unbedingt eindeutig.
Das Ziel Verzeichnis "wächst" nur, da nicht mehr vorhandene Dateien und Ordner der Quelle im Ziel nicht gelöscht werden.
Anderen Problemen/ Verbesserungen bin ich natürlich ebenfalls offen :)
 
Keine Ideen mehr? Ich steh nämlich echt aufm Schlauch :(

Mit dem MD5-Dateivergleich kann ich ja erst einmal leben.
Nur wie schaff ich es in der Quelle nicht mehr vorhandene Dateien und Ordner im Ziel zu löschen?

Brauche bitte Hilfe! :confused:
 
Zurück