Announcement

Collapse
No announcement yet.

Synchronisations Programm

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Synchronisations Programm

    Hallo Community,

    ich bin gerade dabei ein Programm zu schreiben das eine Syncronisation zwischen zwei Ordnern vornehmen soll.

    Das ganze soll zu dem Bi-Direktional funktionieren.

    Doch ich habe jetzt irgendwie einen hänger.

    Nur weis ich jetzt nicht so genau wie ich die Datei änderung erkennen lassen soll.
    Meine bisher mir bekannten möglichkeiten:
    a) Binärvergleich der zwei Dateien
    b) Über das änderungs Datum

    Der Binärvergleich kommt mir etwas ungeignet vor, da eine neuere Datei sowohl kleiner seien kann.

    Beim Änderungs Datum aber müssen auf beiden Ziel-Systemen die gleiche System-Zeit eingestellt sein damit dies funktioniert.

    Ich habe mal was von einer Hash-Bereschnung gehört, könnte mir da einer mal bitte was von erzählen und evtl. einen Beispiel geben?

    Meine zweite Frage ist wie ich am geschicklichsten die Bi-Direktionale Syncronisierung implementiere.

    Ich habe keine ahnung wie ich erkennen soll ob eine Datei auf beiden Seiten geändert wurde.

    Wäre über Hilfe sehr dankbar

  • #2
    Man benutzt oft crc32 für einen schnellen Filevergleich (siehe z.B. hier).

    Ich habe keine ahnung wie ich erkennen soll ob eine Datei auf beiden Seiten geändert wurde.
    Solange du nur die beiden Dateien hast kannst du nur annehmen das die neuere die aktuelle ist und die ältere damit überschreiben. Für mehr brauchst du die Vorversion bzw. Vorversionen der Dateien in den beiden Verzeichnissen. Woher solltest du sonst auch wissen das beide geändert wurden wenn du die Vorversion nicht hast?

    Das machen gängige (kostenlose) Versionscontrolsystem (Git, Mercurial etc.) recht gut. Warum willst du selbst so etwas schreiben?

    Comment


    • #3
      Des Weiteren ist bei einem bidirektionalen Vergleich und der Situation, dass in einem Verzeichniss eine Datei gelöscht wurde eine Entscheidung zu treffen:

      Das Löschen übernehmen
      Die Datei zu kopieren
      Christian

      Comment


      • #4
        Danke erstmal für die schnelle Antworten

        Ju das mit der Entscheidung treffen wusste ich schon, wollte dazu nen EventHandler nehmen. Desweiteren ist die Situation wenn eine Dateien in beiden Ordnern geändert wurde seit dem letzten Sync, welche genommen oder beide behalten werden sollen
        Das mit der Vorversion der Dateien habe ich mir gedacht.

        Soll so ein Programm fürs Studium Programmieren

        Deswegen ist es nicht so gut wenn ich andere Software benutze / einbinde.
        Würde auch sonst das SyncFramwork 2.0 benutzen.
        Aber die Aufgabenstellung lautet halt alles selbst ^^

        Wenn ich jetzt zwei Ordner festlege zum Syncronisieren, wie könnte ich dann das ganze mit der Vorversion realisieren? (Banal alle Dateien in den zu Syncronisierenden Ordner duplizieren? Doch nicht das Gelbe vom Ei)


        Edit:
        Gerade nen Gedanken gehabt.

        Kann ich nicht nach einer Syncronisation in einer Datei das Änderungsdatum speichern. Dann wüsste ich ja das ich beide Dateien nach der Syncronisation geändert wurden.

        Nur hätte ich dann wieder das Problem das auf beiden Systemen die selbe Systemzeit eingestellt sein muss.
        Zuletzt editiert von Vertaxx; 05.06.2010, 21:57.

        Comment


        • #5
          Wenn ich jetzt zwei Ordner festlege zum Syncronisieren, wie könnte ich dann das ganze mit der Vorversion realisieren? (Banal alle Dateien in den zu Syncronisierenden Ordner duplizieren? Doch nicht das Gelbe vom Ei)
          Vielleicht solltest du erst mal feststellen was den genau deine Aufgabenstellung ist. Synchronisieren von Verzeichnissen beinhaltet üblicherweise nicht den Fall das konkurrierende Änderungen an beiden Enden verfolgt werden(das gibt NTFS als Filesystem auch nicht her da müßte man ein anderes versionierendes Filesystem haben). Das ist das Geschäft von Versionskontrolsystem(darum habe ich die erstmal angeführt und keine Compare Tools) und nicht unaufwendig da es seine eigenen zusätzlichen Probleme (Merge von Änderungen in Dateien(und das Dateitypspezifisch!) etc.) mitbringt. Beim synchronisieren wird üblicherweise nur verglichen und bei ungleichheit die neuere über die ältere kopiert.

          Wenn deine Aufgabe nur synchronisieren heißt solltest du Problem von konkurierenden Änderungen erstmal ignorieren und dich auf Fragestellungen wie die von Christian konzentrieren. Wenn du dann immer noch den Fall konkurierender Änderungen verfolgen willst würde ich da einfachheitshalber bei jedem Synchronisieren ein 3.Ordner als Vergleichsoriginal anlegen (je nachdem was du dabei alles erschlagen willst könnte es reichen sich dort Filedatum und den CRC32 Wert (und natürlich die beiden verglichenen Ordner) zu merken.

          Comment


          • #6
            Alles kla danke für die nette Diskussion, hat mir einiges gebracht.
            Werd mich dann wohl mal ans Werk machen.

            Comment


            • #7
              Hallo nochmal,
              irgendwie häng ich gerade an nem kleinen Problem und habe gehofft das ihr mir eventuell helfen könnt.

              Also wiegesagt möchte ich ein Syncronisationsprogramm schreiben.

              Hab mir dazu Gedanken gemacht und habe als erstes eine Methode geschrieben die mir ältere oder nicht vorhandene dateien aus zwei verzeichnissen erkennt:

              Code:
              public static ArrayList CheckFiles (string Quellpfad, string Zielpfad)
                      {
                          //ArrayList in denen die zu Updatenden files reinkommen.
                          ArrayList SyncFiles = new ArrayList();
                          DirectoryInfo dirInfo = new DirectoryInfo(Quellpfad);
              
                          //Rekursiver aufruf für Unterordner
                          foreach (DirectoryInfo Subdirectories in dirInfo.GetDirectories())
                          {
                              SyncFiles.AddRange(CheckFiles(Subdirectories.FullName, Zielpfad + "\\" + Subdirectories.ToString())); 
                          }
              
                          //Überprüfung der Dateien beginnen
                          foreach (FileInfo QuellFile in dirInfo.GetFiles())
                          {
                              FileInfo CheckFile = new FileInfo(Zielpfad + "\\" + QuellFile.Name);
                              //Existiert die Datei nicht
                              if (!CheckFile.Exists)
                              {
                                  SyncFiles.Add(Quellpfad + "\\" + QuellFile.Name);
                              }
                              //Ist die Datei vorhanden und älter
                              else if(QuellFile.LastWriteTime > CheckFile.LastWriteTime)
                              {
                                  string test = Quellpfad + "\\" + QuellFile.Name;
                                  Override(ref SyncFiles, test);    
                              }
                          }
              So jetzt habe ich eine Copy Methode die mir die Dateien in den anderen Ordner kopiert.

              Code:
              public static void CopyToDestination(string file, string Zielpfad)
                      {
                              FileInfo CopyFile = new FileInfo(file);
              
                              // Zielpfad erzeugen
                              StringBuilder newTargetPath = new StringBuilder();
                              {
                                  newTargetPath.Append(Zielpfad);
                                  newTargetPath.Append(CopyFile.DirectoryName.ToString().Substring(Zielpfad.LastIndexOf(@"\")));
                              }
                          
                              // wenn aktueller Ordner nicht existiert -> ersstellen
                              if (!Directory.Exists(newTargetPath.ToString()))
                                  Directory.CreateDirectory(newTargetPath.ToString());
              
                              try
                              {
                                  if (!CopyFile.Exists)
                                      CopyFile.CopyTo(newTargetPath + "\\" + CopyFile.Name);
                                  else
                                      CopyFile.CopyTo(newTargetPath + "\\" + CopyFile.Name, true);
                              }
                              catch(Exception e)
                              {
                                  MessageBox.Show(e.Message);
                              }     
                      }
              Das Problem ist nur das wenn ich jetzt z.B.
              Ordner A (C:\Neuer Ordner) in Ordner B (C:\Neuer Ordner 2) kopieren möchte das ich als Ergebniss C:\Neuer Ordner 2\Neuer Ordner erhalte.
              Ich hätte gern aber nur die Dateien und Ordner aus A in B und nicht den ganzen Ordner.

              kann mir da einer bitte helfen

              Comment


              • #8
                Hallo,

                vereinfache doch zunächst deinen Code:

                1. Du brauchst keinen StringBuilder; das Addieren von Pfad und Dateiname geht auch über String.
                2. Dafür ist Path.Combine das Mittel der Wahl. Das achtet selbst auf korrekten Backslash.
                3. Was schon ein String ist wie DirectoryName, braucht kein ToString.
                4. CopyTo brauchst du nur einmal, nämlich die zweite Variante.

                Nach diesen Vereinfachungen kann man den Code genauer untersuchen; wahrscheinlich findest du selbst bereits die Stelle, an der du Name der Datei und Name eines Verzeichnisses falsch zusammensetzt.

                Nebenbei: ArrayList gehört in die Mottenkiste und sollte wie alle untypisierten Collections aus System.Collections nicht mehr benutzt werden. Verwende stattdessen List<T> und alle anderen typisierten Collections aus System.Collections.Generic.

                Jürgen

                Comment


                • #9
                  Hiermit wäre ich vorsichtig:

                  Code:
                  QuellFile.LastWriteTime > CheckFile.LastWriteTime
                  Windows nimmts da nicht ganz so genau. Wenn dann würde ich die Daten über einen Hash Wert vergleichen.
                  Ausserdem gibt es Methoden um mit FileNamen zu arbeiten, entweder unter der Klasse FileInfo direkt oder die statischen Methoden der Path Klasse.

                  Comment


                  • #10
                    Ok danke für die hilfe erstmal hab das ganze aus nem dotnet snippet kopiert gehabt.

                    Mein Problem ist das ich einen Pfad als String in der Form
                    C:\Neuer Ordner\Neuer Ordner2\test.txt habe

                    und ich kriege es nicht gebacken den Laufwerksbuchstaben und den ersten Ordner abzuschneiden, damit ich nur noch \Neuer Ordner2\test.txt erhalte.

                    Comment


                    • #11
                      String.IndexOf und String.Substring sollten helfen. Bei IndexOf musst du natürlich eine passende Überladung benutzen. Jürgen

                      Comment


                      • #12
                        Du brauchst einfach 3 Sachen die der Benutzer eingeben muss.

                        1. Brauchst Du das Basisverzeichnis das synchronisiert werden soll. In Deinem Fall wäre das:

                        Code:
                        String string1 =  @"C:\Neuer Ordner\"
                        2. In diesem Verzeichnis wählt der Benutzer nun eine (mehrere) Datei(en) aus:

                        Code:
                        String string2 = @"C:\Neuer Ordner\Neuer Ordner2\test.txt habe"
                        Nun kannst Du ganz einfach vom 2. String Zeichen der Länge des 1. Strings vorne wegnehmen:

                        Code:
                        String neu = string2.Remove(0,string1.Length)
                        neu == "Neuer Ordner2\test.txt"
                        3. Noch einen Zielordner definieren

                        Code:
                        String string3 = @"C:\Neuer Ordner2\";
                        4. Daraus die Zieldatei bestimmen:

                        Code:
                        String ziel = Path.Combine(string3, neu)

                        Comment


                        • #13
                          Danke schön das war der knackpunkt auf den ich nicht kommen wollte, der tag ist gerettet

                          Aber ich habe doch noch eine Frage ^^

                          Also ich hab das ja schon so in der art versucht.
                          Nur finde ich es halkt eleganter wenn ich nur 2 Parameter in der Methode habe und nicht 3.
                          Auserdem steckt das Quellverzeichniss ja schon in der File drin.

                          Ich wollte dann so etwas machen wie:

                          file.Substring(file.IndexOf("\\"))
                          dann würde er mir ja bei C:\Neuer Ordner\test.txt
                          \Neuer ordner\test.txt rausgeben.

                          Ich finde halt nicht die passende Überladung damit er nicht das erste sonder alles bis zum zweiten rausnimmt.

                          Habe das ganze dann so versucht:
                          Code:
                          file = "C:\Neuer Ordner\test.txt"
                          string t = file.Substring(file.IndexOf(@"\"));
                          t = "\\Neuer ordner\\test.txt"
                          t.Remove(0,2); //Und hier löscht er leider die  zwei \ nicht
                          string f = t.Substring(t.IndexOf(@"\"));
                          Ach ja und ich habe ein problem mit Path.Combine
                          Code:
                          public static void CopyToDestination(string file, string Quellpfad, string Zielpfad)
                                  {
                                      
                          
                          
                                          // Zielpfad erzeugen
                                          String neu = file.Remove(0,Quellpfad.Length);
                                          String ziel = Path.Combine(Zielpfad, neu);
                          mein string ziel enthält nur neu
                          Zuletzt editiert von Vertax; 07.06.2010, 18:17.

                          Comment


                          • #14
                            Jetzt stell Dir mal vor du bist im 15. Unterordner und möchtest den 12. Synchronisieren? Woher soll dann Deine Funktion wissen welche Ordner synchronisiert werden sollen?

                            c:\temp\test\Ordner1\bla\meineDateien\test.txt

                            Und nun möchtest du nicht c:\temp synchronisieren sondern

                            c:\temp\test\Ordner1

                            Zeig mir mal wie Du Deine Funktion weißsagende Fähigkeiten verpasst.

                            Die Funktion würde ich auf jeden Fall so programmieren. Wenn Du tatsächlich immer den ersten Ordner synchronisieren möchtest ist das ein Spezialfall. Dann kannst Du vom Dateinamen einfach die ersten 2 \ wegnehmen:

                            Code:
                            string datei = @"c:\Neuer Ordner\temp\test.txt";
                            datei = datei.Remove(0,datei.IndexOf(@"\"));
                            datei = datei.Remove(0,datei.IndexOf(@"\"));
                            Edit:

                            Code:
                            t.Remove(0,2); //Und hier löscht er leider die  zwei \ nicht
                            Dazu muss man die String auch richtig benutzen:

                            Code:
                            t = t.Remove(0,1)
                            Ausserdem sind "\\" nicht zwei Zeichen sondern eins. Das ganze nennt man Escape Sequenz und wird dazu benutzt Sonderzeichen darzustellen. So ist z.B. "\t" EIN Zeichen für einen Tabulator. Das sind also nicht 2 Zeichen.

                            Comment

                            Working...
                            X