bestimmte Dateien innerhalb eines Ordners (und Unterordnern) rekursiv ermitteln

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von kwon.

    bestimmte Dateien innerhalb eines Ordners (und Unterordnern) rekursiv ermitteln

    Hallo,

    ich benötige etwas Hilfe, da ich noch nie etwas rekursives programmiert habe...

    Ich möchte innerhalb eines Ordners (mit Unterordnern) bestimmte Dateitypen zählen.

    Ich habe mich an einer Vorlage orientiert, die ich online gefunden habe.

    Irgendwie klappt der Aufruf (in Zeile 12) der Sub Rekursiv nicht - beim debuggen wandert der Cursor einfach weiter und geht nicht in die Sub Rekursiv hinein.

    Ich habe gegoogelt, dass man die Sub, die man aufrufen möchte, einfach hinschreibt und in Klammern Objekte übergibt.

    Außerdem habe ich die Anzahlen klassenweit deklariert, so dass ich den Array a wohl gar nicht brauche (?)

    Bitte helft mir, wie ich es richtig umsetzen kann (die Anzahlen der Dateitypen rekursiv zu ermitteln)...

    Vielen Dank...

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim Anzahl_jpg As Integer = 0, Anzahl_tif As Integer = 0, Anzahl_pdf As Integer = 0
    3. Dim a(2) As Integer
    4. Private Sub ButtonOrdnerWählen_Click(sender As Object, e As EventArgs) Handles ButtonOrdnerWählen.Click
    5. Dim ordner As IO.DirectoryInfo
    6. Dim pfad As String = ""
    7. If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
    8. pfad = FolderBrowserDialog1.SelectedPath
    9. End If
    10. ordner = New IO.DirectoryInfo(pfad)
    11. 'alle Dateien des Ordners ermitteln
    12. Rekursiv(ordner)
    13. Anzahl_jpg = a(0)
    14. Anzahl_tif = a(1)
    15. Anzahl_pdf = a(2)
    16. Me.Label_jpg_Anzahl.Text = Anzahl_jpg.ToString()
    17. Me.Label_jpg_Anzahl.Text = Anzahl_tif.ToString()
    18. Me.Label_jpg_Anzahl.Text = Anzahl_pdf.ToString()
    19. End Sub
    20. Private Sub Rekursiv(ByVal ordner As IO.DirectoryInfo)
    21. Dim unterordner As IO.DirectoryInfo
    22. Dim datei As IO.FileInfo
    23. ' zunächst alle Dateien des Ordners aufspüren
    24. For Each datei In ordner.GetFiles()
    25. a = endu(datei)
    26. Next
    27. ' Jetzt alle Unterverzeichnis durchlaufen
    28. ' und die Prozedur rekursiv selbst aufrufen
    29. For Each unterordner In ordner.GetDirectories()
    30. Rekursiv(unterordner)
    31. Next
    32. End Sub
    33. Function endu(datei As IO.FileInfo) As Array
    34. Dim dateiname As String, posBeginnEndung As Integer, nameEndung As String
    35. dateiname = ""
    36. posBeginnEndung = 0
    37. nameEndung = ""
    38. dateiname = datei.Name.ToString()
    39. posBeginnEndung = InStr(dateiname, ".") + 1
    40. nameEndung = dateiname.Substring(posBeginnEndung)
    41. 'jpg-Ermittlung (auch jpeg)
    42. If nameEndung.Contains("jp") Or nameEndung.Contains("JP") Then
    43. Anzahl_jpg += 1
    44. End If
    45. 'tif-Ermittlung
    46. If nameEndung.Contains("tif") Or nameEndung.Contains("TIF") Then
    47. Anzahl_tif += 1
    48. End If
    49. 'pdf-Ermittlung
    50. If nameEndung.Contains("pdf") Or nameEndung.Contains("PDF") Then
    51. Anzahl_pdf += 1
    52. End If
    53. a(0) = Anzahl_jpg
    54. a(1) = Anzahl_tif
    55. a(2) = Anzahl_pdf
    56. Return a
    57. End Function
    58. End Class
    Bei mir läuft Dein Code problemlos durch.

    Ich schlage vor, dass Du den Code noch etwas aufräumst, dann ist er besser zu lesen und zu warten.

    Z.B. Kannst Du die Zeilen 14-19 in 3 Zeilen zusammen fassen. Me.Label_jpg_Anzahl.Text =a(0).toString()
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    @kwon Was machst Du, wenn die Datei xxx.Pdf heißt?
    Sieh Dir mal die Überladung .GetFiles(String) an, da kannst Du Dein Suchmuster gleich vorgeben:
    docs.microsoft.com/de-de/dotne…o-getfiles(system-string)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    das mit dem Suchmuster wird er kaum brauchen können, wenn er verschiedene Extensions mit einem Durchlauf suchen will.
    Mehrere Durchläufe wären ineffizient.
    Aber trotzdem sind die GetFiles-Überladungen interessant, es gibt da ja auch eine, die bezieht Unterordner mit ein - eine Rekursion selbst zu coden könnte man sich sparen.
    Dazu müsst @kwon aber wissen, was eine Überladung ist, und wie man sich sowas "anschaut".
    @kwon: reichen dir die gegebenen Informationen, oder benötigst du Nachschub auch in derlei Grundlagen-Fragen?

    ErfinderDesRades schrieb:

    Mehrere Durchläufe wären ineffizient.
    Das käme auf einen Versuch an.
    Das System cached da eine ganze Menge an Information.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo @kwon
    1. Option Strict On! -> Visual Studio – Empfohlene Einstellungen
    2. Du weisst dein Ergebnis immer dem selben Label zu (Label_jpg_Anzahl) Zeile 17-19
    3. Kannst du deinen Code stark vereinfachen, indem du entweder den Integer-Array oder die drei Anzahl-Variablen weglässt.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub ButtonOrdnerWählen_Click(sender As Object, e As EventArgs) Handles ButtonOrdnerWählen.Click
    3. Dim ordner As IO.DirectoryInfo
    4. If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
    5. ordner = New IO.DirectoryInfo(FolderBrowserDialog1.SelectedPath)
    6. Else
    7. Exit Sub
    8. End If
    9. 'alle Dateien des Ordners ermitteln
    10. Rekursiv(ordner)
    11. Me.Label_jpg_Anzahl.Text = Anzahl_jpg.ToString()
    12. Me.Label_tif_Anzahl.Text = Anzahl_tif.ToString()
    13. Me.Label_pdf_Anzahl.Text = Anzahl_pdf.ToString()
    14. End Sub
    15. Dim Anzahl_jpg As Integer, Anzahl_tif As Integer, Anzahl_pdf As Integer
    16. Private Sub Rekursiv(ByVal ordner As IO.DirectoryInfo)
    17. Dim unterordner As IO.DirectoryInfo
    18. Dim datei As IO.FileInfo
    19. Dim nameEndung As String
    20. ' zunächst alle Dateien des Ordners aufspüren
    21. For Each datei In ordner.GetFiles()
    22. nameEndung = datei.Extension.ToLower
    23. 'jpg-Ermittlung (auch jpeg)
    24. If nameEndung.StartsWith(".jp") Then
    25. Anzahl_jpg += 1
    26. 'tif-Ermittlung
    27. ElseIf nameEndung.StartsWith(".tif") Then
    28. Anzahl_tif += 1
    29. 'pdf-Ermittlung
    30. ElseIf nameEndung.StartsWith(".pdf") Then
    31. Anzahl_pdf += 1
    32. End If
    33. Next
    34. ' Jetzt alle Unterverzeichnis durchlaufen
    35. ' und die Prozedur rekursiv selbst aufrufen
    36. For Each unterordner In ordner.GetDirectories()
    37. Rekursiv(unterordner)
    38. Next
    39. End Sub
    40. End Class
    @HenryV @kwon Seht Euch mal die Funktion String.EndsWith(...) an.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Die .EndsWith hab ich auch angeschaut, im Gegensatz zu .StartsWith funktioniert aber die Abfrage für .JPEG und .TIFF so dann nicht mehr.
    Ich vergleiche ja denn Anfang der Dateierweiterung, für das Vergleichen mit dem Ende müsste man dann so schreiben: .EndsWith("jpg") OrElse .EndsWith("jpe") OrElse .EndsWith("jpeg") und .EndsWith("tif") OrElse .EndsWith("tiff")

    Um aber ganz sicher nur Richtige und nicht irgendwelche Falsch-Positive Ergebnisse zu erhalten, müsste man wirklich jede Variante der Dateierweiterung für den Dateityp abfragen.
    Also nicht nur Anfang oder Ende vergleichen, sondern die ganze Dateierweiterung mit allen zulässigen Varianten.
    Dankeschön an alle fleißigen Menschen!!

    Mir reichen die dargestellten Informationen...

    Ich gebe mich sehr gerne mit dem Beispiel von HenryV zufrieden...

    Dass ich übersehen/vergessen habe, in Zeile 17-19 die Anzahlen umzubenennen war ein guter Hinweis.

    Ich hatte vermutet, dass man entweder die 3 Anzahlen braucht oder Array a - (aber nicht beide).

    Ich werde mir am Wochenende mal die GetFiles-Überladungen anschauen, bin gerade auf der Arbeit...
    Allerdings vermute ich, dass ich evtl. wenig damit anfangen kann, da ich kein Profi bin - aber einen Blick ist es wert (wenn man sich sparen kann die Rekursion selbst zu programmieren).

    Vielen Dank für die Hilfe an alle!!!

    Das Tool macht, was es soll...

    Dankeschön...
    Hi @kwon
    du hast zwar schon eine Lösung, versuche aber trotzdem mal so..
    beachte "GetExtension"

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. ''gezielt suchen:
    3. 'Dim extensions() As String = {"*.txt", "*.jpg", "*.xlsx"}
    4. 'Dim filePaths = FileIO.FileSystem.GetFiles("D:\DeinPfad", FileIO.SearchOption.SearchAllSubDirectories, extensions)
    5. ''alles suchen :
    6. Dim filePaths = Directory.GetFiles("D:\DeinPfad", "*",
    7. SearchOption.AllDirectories)
    8. Dim fileCountsByType = filePaths.GroupBy(Function(filePath) _
    9. Path.GetExtension(filePath).ToLower(),
    10. Function(extension, group) _
    11. New With {Key extension, group.Count()}).
    12. OrderByDescending(Function(group) group.Count)
    13. ListBox1.Items.AddRange(fileCountsByType.Select(Function(group) _
    14. String.Format("{0} Datei(en) mit ""{1}"" Dateitype", group.Count, group.extension)).ToArray())
    15. End Sub