none
Datum vergleichen RRS feed

  • Frage

  • Hallo,

    ich möchte 2 Dateien vergleichen ob das Datum der letzten Änderung unterschiedlich ist.
    Dazu habe ich folgenden Code:

    foreach (string suche_aktuell1 in Directory.GetFiles("c:\\Daten", "*.*", SearchOption.AllDirectories))
                {
                    foreach (string suche_aktuell2 in Directory.GetFiles("c:\\Daten1\\", "*.*", SearchOption.AllDirectories))
                    {
                        string aktuell1 = Path.GetFileName(suche_aktuell1);
                        string aktuell2 = Path.GetFileName(suche_aktuell2);
                        FileInfo aktuell1a = new FileInfo(suche_aktuell1);
                        FileInfo aktuell2a = new FileInfo(suche_aktuell2);
    
                        if (aktuell1.Equals(aktuell2))
                        {
                            if (aktuell1a.LastWriteTime != aktuell2a.LastWriteTime)
                            {
                                list_datum.Add(suche_aktuell1);
                            }
                        }
                    }
                }

    aber irgendwie will er ned so richtig mir die Dati wenn das Datum unterschiedlich ist in die List eintragen.

    Listen sind erstellt nur ned im Code enthalten.

    Wenn jemand einen hinweis hat her damit :)

    danke


    cay

    Montag, 11. März 2013 14:10

Antworten

  • Hallo Cay,

    es empfiehlt sich die UTC-Zeiten zu verwenden.

    Und anstatt für jede Dateinamen einen vollständigen Durchlauf zu machen, sollte man zuerst eine Auflistung bilden und dort nachschauen. Eine mögliche Variante kurz angedeutet:

    string Verzeichnis1 = @"C:\TEMP\Test1";
    string Verzeichnis2 = @"C:\TEMP\Test2";
    
    var dateien = new Dictionary<string, FileInfo>(StringComparer.InvariantCultureIgnoreCase);
    foreach(string dateiName in Directory.GetFiles(Verzeichnis1))
    {
        var dateiInfo = new FileInfo(dateiName);
        dateien.Add(dateiInfo.Name, dateiInfo);
    }
    
    foreach (string dateiName in Directory.GetFiles(Verzeichnis2))
    {
        var dateiInfo = new FileInfo(dateiName);
        if (dateien.ContainsKey(dateiInfo.Name))
        {
            if (dateiInfo.LastWriteTimeUtc == dateien[dateiInfo.Name].LastWriteTimeUtc)
            {
                Console.WriteLine("Datei gleich: " + dateiName);
            }
        }
    }
    Gruß Elmar

    Montag, 11. März 2013 15:37
    Beantworter
  • Hallo zusammen,

    und hier noch eine Version, die etwas weniger imperativ daherkommt und in der Verwendung ebenfalls recht einfach ist: FileComparer.GetModifiedFiles(x, y).

    public class FileComparer : IEqualityComparer<string> {
        public static IEnumerable<string> GetModifiedFiles(string dir1, string dir2) {
            var files1 = Directory.GetFiles(dir1, "*.*", SearchOption.AllDirectories);
            var files2 = Directory.GetFiles(dir2, "*.*", SearchOption.AllDirectories);
            return files1.Intersect(files2, new FileComparer());
        }
    
        public bool Equals(string x, string y) {
            if (x == null || y == null) return false;
            return System.IO.Path.GetFileName(x) == System.IO.Path.GetFileName(y) &&
                    new FileInfo(x).LastWriteTime != new FileInfo(y).LastWriteTime;
        }
    
        public int GetHashCode(string obj) {
            if (obj == null) return 0;
            return System.IO.Path.GetFileName(obj).GetHashCode();
        }
    }
    

    Gruß
    Marcel

    • Als Antwort markiert joksch_c Freitag, 15. März 2013 12:11
    Montag, 11. März 2013 19:20
    Moderator
  • Abhängig davon, was dein Endziel ist, könnte dir u.U. auch folgende Klasse weiterhelfen:

    public class DirectoryComparer 
    {
        public static IEnumerable<string> GetModifiedFiles(string originalsDirectory, string modifiedDirectory)
        {
            var files1 = Directory.EnumerateFiles(originalsDirectory, "*.*", SearchOption.AllDirectories);
            var files2 = Directory.EnumerateFiles(modifiedDirectory, "*.*", SearchOption.AllDirectories);
    
            var query = from f1 in files1
                        join f2 in files2 on
                             new { FileName = System.IO.Path.GetFileName(f1) } equals
                             new { FileName = System.IO.Path.GetFileName(f2) }
                        where new FileInfo(f1).LastWriteTime != new FileInfo(f2).LastWriteTime 
                        select f2;
    
            return query;
        }
    }
    

    Gruß
    Marcel

    • Als Antwort markiert joksch_c Freitag, 15. März 2013 12:11
    Dienstag, 12. März 2013 11:20
    Moderator
  • Arbeite resourcenschonender und trennen Erstellung der Dateilisten vom Vergleich. Z.B. wie hier: Checking file size and writing to text file any 0 value file names..... Dann reicht folgende Erweiterung:

    public class FolderDiff
    {
    // ..
      public void CompareLastWriteTime()
      {
        foreach (FileInfo baseFileInfo in this.baseFiles)
        {
          foreach (FileInfo compareFileInfo in this.compareFiles)
          {
            if (baseFileInfo.Name.Equals(compareFileInfo.Name))
            {
              if (baseFileInfo.LastWriteTime != compareFileInfo.LastWriteTime)
              {
                Console.WriteLine("LastWriteAccess different for {0}.", baseFileInfo.Name);
              }
            }
          }
        }
      }
    }

    • Als Antwort markiert joksch_c Freitag, 15. März 2013 12:11
    Montag, 11. März 2013 15:30

Alle Antworten

  • Arbeite resourcenschonender und trennen Erstellung der Dateilisten vom Vergleich. Z.B. wie hier: Checking file size and writing to text file any 0 value file names..... Dann reicht folgende Erweiterung:

    public class FolderDiff
    {
    // ..
      public void CompareLastWriteTime()
      {
        foreach (FileInfo baseFileInfo in this.baseFiles)
        {
          foreach (FileInfo compareFileInfo in this.compareFiles)
          {
            if (baseFileInfo.Name.Equals(compareFileInfo.Name))
            {
              if (baseFileInfo.LastWriteTime != compareFileInfo.LastWriteTime)
              {
                Console.WriteLine("LastWriteAccess different for {0}.", baseFileInfo.Name);
              }
            }
          }
        }
      }
    }

    • Als Antwort markiert joksch_c Freitag, 15. März 2013 12:11
    Montag, 11. März 2013 15:30
  • Hallo Cay,

    es empfiehlt sich die UTC-Zeiten zu verwenden.

    Und anstatt für jede Dateinamen einen vollständigen Durchlauf zu machen, sollte man zuerst eine Auflistung bilden und dort nachschauen. Eine mögliche Variante kurz angedeutet:

    string Verzeichnis1 = @"C:\TEMP\Test1";
    string Verzeichnis2 = @"C:\TEMP\Test2";
    
    var dateien = new Dictionary<string, FileInfo>(StringComparer.InvariantCultureIgnoreCase);
    foreach(string dateiName in Directory.GetFiles(Verzeichnis1))
    {
        var dateiInfo = new FileInfo(dateiName);
        dateien.Add(dateiInfo.Name, dateiInfo);
    }
    
    foreach (string dateiName in Directory.GetFiles(Verzeichnis2))
    {
        var dateiInfo = new FileInfo(dateiName);
        if (dateien.ContainsKey(dateiInfo.Name))
        {
            if (dateiInfo.LastWriteTimeUtc == dateien[dateiInfo.Name].LastWriteTimeUtc)
            {
                Console.WriteLine("Datei gleich: " + dateiName);
            }
        }
    }
    Gruß Elmar

    Montag, 11. März 2013 15:37
    Beantworter
  • Die Verwendung von ContainsKey mit einem Dictionary ist interessant, allerdings problematisch, da mit SearchOptions.AllDirectories auch Unterverzeichnisse durchlaufen werden und damit Dateinamen nicht mehr zwingend eindeutig sind. Auch reicht eigentlich ein
    dateien.Add(dateiInfo.Name, dateiInfo);
    Montag, 11. März 2013 16:04
  • Hallo Stefan ,

    das war nur schnell runter getippt - Deine Lösung im US-Bereich gefiele mir auch besser ;) Nur hatte ich Deine Antwort da noch nicht gesehen.

    Ich hatte bewusst auf AllDirectories verzichtet, auch wenn es im Ausgangsbeispiel vorkam. Denn nicht klar war: Sind die Unterverzeichnis-Strukturen gleich und Cay verwendet  nur den Dateinamen weiter (ich hatte anfangs eine SubString... Lösung drin).

    Das Dateinamenvergleiche u. U. problematisch sind kommt hinzu, auch wenn ich vermute, dass wir es hier eher mit einem deutschen Subset zu tun haben, der Vollständigkeit halber: Comparing Unicode file names the right way

    Gruß Elmar

    Montag, 11. März 2013 16:42
    Beantworter
  • Hallo zusammen,

    und hier noch eine Version, die etwas weniger imperativ daherkommt und in der Verwendung ebenfalls recht einfach ist: FileComparer.GetModifiedFiles(x, y).

    public class FileComparer : IEqualityComparer<string> {
        public static IEnumerable<string> GetModifiedFiles(string dir1, string dir2) {
            var files1 = Directory.GetFiles(dir1, "*.*", SearchOption.AllDirectories);
            var files2 = Directory.GetFiles(dir2, "*.*", SearchOption.AllDirectories);
            return files1.Intersect(files2, new FileComparer());
        }
    
        public bool Equals(string x, string y) {
            if (x == null || y == null) return false;
            return System.IO.Path.GetFileName(x) == System.IO.Path.GetFileName(y) &&
                    new FileInfo(x).LastWriteTime != new FileInfo(y).LastWriteTime;
        }
    
        public int GetHashCode(string obj) {
            if (obj == null) return 0;
            return System.IO.Path.GetFileName(obj).GetHashCode();
        }
    }
    

    Gruß
    Marcel

    • Als Antwort markiert joksch_c Freitag, 15. März 2013 12:11
    Montag, 11. März 2013 19:20
    Moderator
  • So gerade erst wieder Online und ich werde mir die verschiedenen Versionen mal anschauen wenn alle gehen werde ich natürlich auch alle Als Antwort markieren.

    grüße


    cay

    Dienstag, 12. März 2013 11:13
  • Abhängig davon, was dein Endziel ist, könnte dir u.U. auch folgende Klasse weiterhelfen:

    public class DirectoryComparer 
    {
        public static IEnumerable<string> GetModifiedFiles(string originalsDirectory, string modifiedDirectory)
        {
            var files1 = Directory.EnumerateFiles(originalsDirectory, "*.*", SearchOption.AllDirectories);
            var files2 = Directory.EnumerateFiles(modifiedDirectory, "*.*", SearchOption.AllDirectories);
    
            var query = from f1 in files1
                        join f2 in files2 on
                             new { FileName = System.IO.Path.GetFileName(f1) } equals
                             new { FileName = System.IO.Path.GetFileName(f2) }
                        where new FileInfo(f1).LastWriteTime != new FileInfo(f2).LastWriteTime 
                        select f2;
    
            return query;
        }
    }
    

    Gruß
    Marcel

    • Als Antwort markiert joksch_c Freitag, 15. März 2013 12:11
    Dienstag, 12. März 2013 11:20
    Moderator