Benutzer mit den meisten Antworten
Ordnerinhalte vergleichen

Frage
-
Hallo zusammen, ich schreibe momentan an einem Synchronisierungs-Tool.
Hier muss ich 2 Ordner miteinander vergleichen. Und zwar befinden sich in beiden Ordnern Fotos. In Ordner A kommen szändig neue Fotos hinzu. Nun möchte ich beide Ordner miteinander vergleichen und nur die Fotos, die in Ordner A sind, aber noch nicht in Ordner B, in den Ordner B kopieren.
Kann mir hier jemand weiterhelfen?
Mfg
RK
Antworten
-
Das funktioniert aber nicht mit .NET 4.5. VS 2010 ist auf 4.0 beschränkt.
Ich habe es aber nochmal bei mir getestet. Yield wird auch unter VS 2012 SP1 nicht unterstützt. Hier hast du nochmal meinen umgeschriebenen Code:
Sub Main() Dim pathA = "D:\Test\A" Dim pathB = "D:\Test\B" Dim res = CompareFolders(pathA, pathB) For Each file In res Dim fldr = New FileInfo(file.Replace(pathA, pathB)).Directory.FullName 'Raplace um "A" durch "B" zu tauschen' If Not Directory.Exists(fldr) Then Directory.CreateDirectory(fldr) 'Ordner erstellen falls nicht vorhanden' End If System.IO.File.Copy(file, file.Replace(pathA, pathB)) 'Datei kopieren' Next End Sub ''' <summary>' ''' Vergleicht die Dateien in A mit den Dateien in B und gibt eine Liste von Dateinamen zurück, die in A, aber nicht in B enthalten sind.' ''' </summary>' Function CompareFolders(pathA As String, pathB As String) As List(Of String) Dim result As New List(Of String)() Dim filesA = Directory.GetFiles(pathA) 'Dateien von A auslesen' Dim filesB As String() 'Wenn b nicht existiert, dann wird ein leeres Array genommen > Alle Dateien werden zurück gegeben' If Directory.Exists(pathB) Then filesB = Directory.GetFiles(pathB) Else filesB = New String() {} 'Leeres Array' End If For i As Integer = 0 To filesA.Length - 1 'Nacholgende Abfrage überprüft, ob eine Datei schon vorhanden ist. Ggf. eine bessere Methode zum vergleichen aufbauen' If Not filesB.Contains(filesA(i).Replace(pathA, pathB)) Then result.Add(filesA(i)) 'Gebe die einzelne Datei zurück, die in B nicht vorhanden ist' End If Next For Each folder In Directory.GetDirectories(pathA) For Each res In CompareFolders(folder, folder.Replace(pathA, pathB)) 'Rekursiv für jeden Ordner aufrufen' result.Add(res) 'Die einzelnen Ergebnisse des rekursiven Aufrufs zurück geben' Next Next Return result End Function
Den konnte ich problemlos im VS 2012 SP1 unter .NET 4.0 kompilieren.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Robbo1984 Dienstag, 18. März 2014 07:00
Alle Antworten
-
Hi Robbo1984,
zu deiner Frage. Ja hier können, dir sicher einige Helfen.
Zum Rest, ein bischen Eigenleistung, wo ist den genau dein Problem.
Bestimmen des Ordner inhalts, abgleich der Daten oder das Kopieren?
Gib einfach mal an was du schon hast, gegebenen fals Quellcode. Und beschreib dann dein Problem möglichst genau.
MFG
Björn -
Hallo,
zunächst musst du unterscheiden, wie die Dateien verglichen werden sollen:- Nur anhand der Namen. i.d.R. sollte das ausreichen. Dabei musst du dir aber zu 100% sicher sein, das 2 Dateien niemals gleich heißen. (Im selben Ordner)
- Du vergleichst wirklich die Dateiinhalte. Das ist deutlich aufwendigr und dauert um ein vielfaches länger als 1.
Der Einfachheit halber ist nachfolgendes Beispiel mit der Methode von 1. geschrieben:
Sub Main() Dim pathA = "D:\Test\A" Dim pathB = "D:\Test\B" Dim res = CompareFolders(pathA, pathB).ToList() 'ToList() ist nur fürs Debuggen, damit man im ToolTip auch eine Auflistung finden kann' For Each file In res Dim fldr = New FileInfo(file.Replace(pathA, pathB)).Directory.FullName'Raplace um "A" durch "B" zu tauschen' If Not Directory.Exists(fldr) Then Directory.CreateDirectory(fldr) 'Ordner erstellen falls nicht vorhanden' End If System.IO.File.Copy(file, file.Replace(pathA, pathB))'Datei kopieren' Next End Sub ''' <summary>' ''' Vergleicht die Dateien in A mit den Dateien in B und gibt eine Liste von Dateinamen zurück, die in A, aber nicht in B enthalten sind.' ''' </summary>' Iterator Function CompareFolders(pathA As String, pathB As String) As IEnumerable(Of String) Dim filesA = Directory.GetFiles(pathA) 'Dateien von A auslesen' Dim filesB As String() 'Wenn b nicht existiert, dann wird ein leeres Array genommen > Alle Dateien werden zurück gegeben' If Directory.Exists(pathB) Then filesB = Directory.GetFiles(pathB) Else filesB = New String() {}'Leeres Array' End If For i As Integer = 0 To filesA.Length - 1 'Nacholgende Abfrage überprüft, ob eine Datei schon vorhanden ist. Ggf. eine bessere Methode zum vergleichen aufbauen' If Not filesB.Contains(filesA(i).Replace(pathA, pathB)) Then Yield filesA(i) 'Gebe die einzelne Datei zurück, die in B nicht vorhanden ist' End If Next For Each folder In Directory.GetDirectories(pathA) For Each res In CompareFolders(folder, folder.Replace(pathA, pathB)) 'Rekursiv für jeden Ordner aufrufen' Yield res 'Die einzelnen Ergebnisse des rekursiven Aufrufs zurück geben' Next Next End Function
Ich habe das Beispiel nicht sehr ausführlich getestet und man kann es noch um Einiges effektivieren. Aber es sollte dir einen Ansatz bieten. Um die Dateien Byte für Byte zu vergleichen, findest du hier eine Möglichkeit.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Bearbeitet Tom Lambert (Koopakiller)Moderator Montag, 17. März 2014 19:41 Code Format
-
mein Problem ist: ich hole mir die dateien aus ordner A und auch die aus Ordner B. in A findet er 6 Dateien und in B nur 3. Ist auch vollkommen richtig so. aber wie sage ich ihm jetzt dass er diese 3 kopieren soll, die nicht vorhanden sind. Nutze ich obene ge
Private Sub SyncWundendokumente() Dim pathA = "C:\Users\Public.....PicsA" Dim pathB = "C:\Users\Public.....PicsB" Dim filesA() As String Dim filesB() As String If IO.Directory.Exists(pathA) Then 'Alle Dateien aus dem Ordner auslesen filesA = IO.Directory.GetFiles(pathA) If IO.Directory.Exists(pathB) Then filesB = Directory.GetFiles(pathB) For i As Integer = 0 To filesA.Length - 1 For Each File In filesA If Not filesB.Contains(filesA(i).Replace(pathA, pathB)) Then End If Next Next End If End If End Sub
gebenes Beispiel entstehen nur Fehler.... -
Was sind denn das für Fehler? Poste diese bitte immer Vollständig mit Zeilenangabe.
Fehlt dir vielleicht noch folgender Namespace?
Imports System.IO
In meinem Code oben gehe ich alle Dateien in einem Ordner durch. Sobald eine Datei in B fehlt, wird diese mittels Yield zurück gegeben. Am Ende rufst sich die Methode rekursiv mit allen Unterordnern auf.Nach dem Aufruf der Methode erhält man eine Auflistung von Fehlenden Dateien. Diese kopiere ich dann in einer Schleife. (Zuvor wird ggf. der beinhaltende Ordner erstellt).
Deinen Codeschnippsel verstehe ich nun allerdings nicht so ganz. Es scheint auf meinem Code zu bassieren, aber alles zusammen in einer Methode. Das kann so aber nicht funktionieren, da sich CompareFolders selbst aufruft um die Unterordner zu vergleichen. Es muss also eine extra Methode dafür geben.
Versuche meinen Code zu verstehen. Erstelle dir einfach mal eine kleine Ordnerhierachie die du übertragen möchtest. Dann kannst du mit F11 Zeile für Zeile ausführen und so den Ablauf des ganzen verstehen. Wenn du auf eine Variable zeigst, erfährst du deren Inhalt.Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Zu CompareFolders wird nichts erkannt:
Wenn du meinen COde nur kopierst ohne ihn zu verstehen kann es nicht funktionieren. CompareFolders ist die Funktion, in der sie sich selbst aufrufst um die Unterordner zu vergleichen.Zum Yield wird nicht erkannt:
Return würde nur ein Element zurück geben. Yield dagegen gibt ein Element einer Liste zurück.
Da du meinen Code nur kopiert hast: Eine Sub kann nichts zurück geben, im Gegensatz zu einer Function.Ich für meinen Teil habe alles mittlerweile 2mal erklärt. Verstehe meinen Code, dann helfe ich dir auch gerne weiter.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Hi,
welche .NET Frameworkversion setzt Du für dieses Projekt ein? Welches .NET Framework Profil? (Falls Client Profile, ändere das mal auf die normale Variante)
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Was benutzt du denn für ein VS? Soweit ich weiß ist Yield erst ab VS 2010 SP1 verfügbar.
Alternativ kannst du auch alle Dateipfade zu einer List(Of String) hinzufügen und dann alles gebündelt zurück geben. So sparrst du dir das Yield. Das ist zwar nicht so schön wie ich finde, aber die einzige Möglichkeit in älteren VB.NET's.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Das funktioniert aber nicht mit .NET 4.5. VS 2010 ist auf 4.0 beschränkt.
Ich habe es aber nochmal bei mir getestet. Yield wird auch unter VS 2012 SP1 nicht unterstützt. Hier hast du nochmal meinen umgeschriebenen Code:
Sub Main() Dim pathA = "D:\Test\A" Dim pathB = "D:\Test\B" Dim res = CompareFolders(pathA, pathB) For Each file In res Dim fldr = New FileInfo(file.Replace(pathA, pathB)).Directory.FullName 'Raplace um "A" durch "B" zu tauschen' If Not Directory.Exists(fldr) Then Directory.CreateDirectory(fldr) 'Ordner erstellen falls nicht vorhanden' End If System.IO.File.Copy(file, file.Replace(pathA, pathB)) 'Datei kopieren' Next End Sub ''' <summary>' ''' Vergleicht die Dateien in A mit den Dateien in B und gibt eine Liste von Dateinamen zurück, die in A, aber nicht in B enthalten sind.' ''' </summary>' Function CompareFolders(pathA As String, pathB As String) As List(Of String) Dim result As New List(Of String)() Dim filesA = Directory.GetFiles(pathA) 'Dateien von A auslesen' Dim filesB As String() 'Wenn b nicht existiert, dann wird ein leeres Array genommen > Alle Dateien werden zurück gegeben' If Directory.Exists(pathB) Then filesB = Directory.GetFiles(pathB) Else filesB = New String() {} 'Leeres Array' End If For i As Integer = 0 To filesA.Length - 1 'Nacholgende Abfrage überprüft, ob eine Datei schon vorhanden ist. Ggf. eine bessere Methode zum vergleichen aufbauen' If Not filesB.Contains(filesA(i).Replace(pathA, pathB)) Then result.Add(filesA(i)) 'Gebe die einzelne Datei zurück, die in B nicht vorhanden ist' End If Next For Each folder In Directory.GetDirectories(pathA) For Each res In CompareFolders(folder, folder.Replace(pathA, pathB)) 'Rekursiv für jeden Ordner aufrufen' result.Add(res) 'Die einzelnen Ergebnisse des rekursiven Aufrufs zurück geben' Next Next Return result End Function
Den konnte ich problemlos im VS 2012 SP1 unter .NET 4.0 kompilieren.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Als Antwort markiert Robbo1984 Dienstag, 18. März 2014 07:00