Durchsuchen von Ordnern mit Ordnertiefe

  • VB.NET

Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Durchsuchen von Ordnern mit Ordnertiefe

    Hallo,

    ich suche nach einer Funktion in VB mit der Pfade durchsucht werden können. Dabei sollen bestmöglich alle Unterpfade gelistet werden.
    Ich stelle mir das so vor Pfad C:\ Tiefe:1 C:\Progs, C:\Win ....

    Ich bin bereits auf SearchOption.AllDirectories gestoßen, leider kann man hier aber nicht die Pfadtiefe angeben, als Parameter oder dergleichen.

    Weiß zufällig Jemand, ob es hierfür schon eine passende Funktion gibt?

    VB.neter0101 schrieb:

    Dabei sollen bestmöglich alle Unterpfade gelistet werden.

    VB.neter0101 schrieb:

    leider kann man hier aber nicht die Pfadtiefe angeben
    Ja was denn nun?
    Sollen alle Unterverzeichnisse bis zur dritten Ebene gelistet werden?
    Mach eine Lösung dafür und poste die unter Tipps und Tricks. :thumbsup:
    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!

    VB.neter0101 schrieb:

    Pfadtiefe
    Da gibt es genau die beiden Optionen Nur dieses Verzeichnis und Alle Unterordner.
    Ich hatte noch nie das Bedürfnis, eine Begrenzung dazwischen haben zu müssen.
    Kannst Du das etwas motivieren?
    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 schrieb:


    Ich hatte noch nie das Bedürfnis, eine Begrenzung dazwischen haben zu müssen.


    Hatte ich bis dato auch noch nicht akut.

    @VB.neter0101 gibts für diesen Wunsch einen akuten Anwendungsfall, oder experimentierst du einfach nur ein wenig rum?
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Ich hatte für ähnliches schon öfter Bedarf.
    Hab mir auch was dazu gebastelt: Einen "Rekursions-Iterator".
    Bei dem kann man jederzeit die Tiefe abfragen, und dann auch eine Einstellung machen, den jeweiligen Unter-Zweig zu überspringen.
    Sowas kann bei Suchen in Bäumen erheblichen Performance-Gewinn bringen.

    Aber meine Bastelei ist allgemein gehalten - nicht speziell für Directories.
    Und man muss die Prinzipien von Rekursion verstanden haben, und enen Delegaten formulieren können und sowas.
    Ach habich in c# veröffentlicht - grad im Kontext eines Tuts über Rekursion:
    mycsharp.de/wbb2/thread.php?postid=343618#post343618

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Naja, wenn das nur ein Experiment ist, dann experimentiere mal. Ne fertige Lösung ist ja dann gar nicht sinnvoll ;)
    Hab grad auch ein wenig rum experimentiert ​-> Brauchst nur nen paar Schleifen, Listen und die Directory.GetDirectories() Methode. Sind schätzungsweise +/-10 Zeilen Code :thumbsup:
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen

    mrMo schrieb:

    Brauchst nur nen paar Schleifen, Listen und die Directory.GetDirectories() Methode. Sind schätzungsweise +/-10 Zeilen Code


    10 Zeilen?? Nicht schlecht, wenn du Lust hast, kannst du mir das gerne zeigen? Ich habe zwar auch schon ein paar Einfälle, aber ich glaube die werden nicht die beste Laufzeit haben.

    @ErfinderDesRades das werde ich mir mal ansehen danke!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB.neter0101“ ()

    @VB.neter0101

    So aus dem Kopf gesagt, braucht es dazu nur eine rekursive Funktion einen Zähler (immer +1) plus eine Variable die den MaxWert vom Counter speichert, eine Schleife und eine Liste sofern man die Pfad-verzeichnisse festhalten will.

    Ein gutes Übungsbeispiel. Viel Erfolg.

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    VB.neter0101 schrieb:

    kannst du mir das zeigen?
    Hatten wir nicht gerade festgestellt, dass wohl nur Du das brauchst und sonst eher niemand?
    Wenn Du experimentieren willst, dann experimentiere und überrasche uns mit Deiner Lösung. :thumbsup:
    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!
    Naja prinzipielles Vorgehen wäre denke ich ne Funktion zu erstellen, die sich rekursiv aufruft.
    Also müsstest zwei Parameter haben die eingegeben werden, der Pfad (oder direkt nen DirectoryInfo) und die Tiefe.
    Dann würde ich zwei optionale Parameter dazu packen, die aktuelle Tiefe und die bereits gefundenen Ordner als List (of DirectoryInfo) und dann nen Return einer List (of DirectoryInfo).
    Innerhalb der Funktion muss halt die Liste der gefundenen Ordner so lange ergänzt werden, bis keine neuen mehr gefunden werden, oder die Tiefe der Maximalen Tiefe entspricht... Dann die gefundenen Ordner Returnen.
    Sonst halt immer sich selbst aufrufen mit "TopDirectoryOnly" als Searchoption.
    Problematisch ist dabei nur, dass es Ordner gibt, wo die Suche keine Zugriffsrechte hat, da müsste man den Fehler abfangen. Hierzu hab ich aber bis auf nen Try Catch auch noch nix gescheites gefunden.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Hallo und Gday ;)

    Also ich habe etwas gebastelt, ich habe jetzt ein Programm, dass die Dateien und Ordner listet.

    Ich benötige aber etwas Unterstützung.

    1.) Ich würde gerne die Tiefe angeben, habe bis jetzt aber noch keinen Einfall, wie das zu realisieren ist
    2.) es werden aktuell nur befüllte Ordner gelistet, da habe ich auch noch keinen Einfall
    3.) Der Rückgabewert der Funktionen bringt eigentlich nichts, da return 0 (und ich eigentlich nichts returnen möchte). Ich Java würde ich daraus einfach eine void Methode machen, aber wie geht das in VB.net?

    Wenn mir jemand helfen könnte, wäre das echt hilfreich!

    VB.NET-Quellcode

    1. Dim ListefuerOrdner As New ArrayList()
    2. Public Function RekursivOrdner(Pfad As DirectoryInfo) As Integer
    3. Try
    4. 'Durchlaufe die Verzeichnisse
    5. For Each subVerzeichnis As DirectoryInfo In Pfad.GetDirectories()
    6. RekursivOrdner(subVerzeichnis)
    7. Next
    8. 'Dateien durchsuchen und listen
    9. For Each Datei As FileInfo In Pfad.GetFiles()
    10. Console.Write(Datei.FullName + vbCr)
    11. If ListefuerOrdner.Contains(Datei.DirectoryName) Then
    12. 'Mache nichts, da Element bereits enthalten
    13. Else
    14. ListefuerOrdner.Add(Datei.DirectoryName)
    15. End If
    16. TextBox1.Text += Datei.FullName + vbNewLine
    17. 'TextBox2.Text += Datei.DirectoryName + vbNewLine
    18. Next
    19. Catch ex As Exception
    20. Console.WriteLine(ex.Message)
    21. End Try
    22. Return 0
    23. End Function
    24. Public Function RekursivOrdner(Verz As String) As Integer
    25. RekursivOrdner(New DirectoryInfo(Verz))
    26. Return 0
    27. End Function

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB.neter0101“ ()

    Hier eine kleine Unterstüzung nur für die Verzeichnisse wie das aussehen könnte.

    VB.NET-Quellcode

    1. Private Function GetAllDir(ByVal sPath As String, ByRef lstDir As List(Of String), ByVal ic As Integer) As Boolean
    2. For Each d As String In Directory.GetDirectories(sPath)
    3. ic += 1
    4. lstDir.Add(String.Format("{0} [Tiefe = {1}]", d, ic.ToString))
    5. Try
    6. GetAllDir(d, lstDir, ic)
    7. Catch ex As Exception
    8. End Try
    9. ic -= 1
    10. Next
    11. Return True
    12. End Function


    Ist aber keineswegs ausgereift.

    Freundliche Grüsse

    exc-jdbi

    exc-jdbi schrieb:

    ByRef lstDir As List(Of String)
    solltest du ByVal übergeben.
    Du willst innerhalb der Funktion ja nicht die Liste gegen eine andere austauschen, sondern die bestehende Liste erweitern.

    Abgesehen davon würde ich die wahrscheinlich nicht übergeben, sondern eher in der darüberliegenden Struktur speichern.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    So, ich habe etwas weiter probiert. Ich kann jetzt alle Ordner durchlaufen lassen. Die Tiefe kann ich leider noch immer nicht angeben, da benötige ich etwas Hilfe ;)


    Ist das vllt machbar bzw von der Laufzeit her gut?
    --> Durchsuche die Liste nach \ und zähle die \, wenn Anzahol von \ größer als xy dann lösche es?
    Das Problem ist, dass ich dann dennoch alle Verzeichnisse durchgehe und zusätzlich die Liste, die Laufzeit würde sich dann erheblich erhöhen, geht sowas auch performanter, oder anders?

    VB.NET-Quellcode

    1. Public Function FunktionFürOrdner(Pfad As String) As Integer
    2. Try
    3. For Each strFile As String In Directory.GetFiles(Pfad)
    4. Next
    5. For Each Verzeichnis As String In Directory.GetDirectories(Pfad)
    6. FunktionFürOrdner(Verzeichnis)
    7. If ListefuerOrdner.Contains(Verzeichnis) Then
    8. Else
    9. ListefuerOrdner.Add(Verzeichnis)
    10. End If
    11. Next
    12. Catch ex As Exception
    13. Console.WriteLine(ex.Message)
    14. End Try
    15. Return 0
    16. End Function


    VB.NET-Quellcode

    1. Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
    2. FunktionFürOrdner("F:\OFFUFD")
    3. ListefuerOrdner.Sort()
    4. For Each el In ListefuerOrdner
    5. TextBox2.Text += el + vbNewLine
    6. Next
    7. MessageBox.Show("Ordner gefunden: " & ListefuerOrdner.Count)
    8. End Sub
    1. Wenn Du eh nix aus der Funktion zurückgeben willst, dann schreib statt Public Function FunktionFürOrdner(Pfad As String) As Integer Public Sub FunktionFürOrdner(Pfad As String). Das ist VB.NET-Grundsatz-Must-Have-Wissen.
    2. Zu Deiner Maximaltiefe: Dann gib Deiner (jetzt) Sub-Prozedur eben noch einen Parameter aktTiefe As Integer mit:

    VB.NET-Quellcode

    1. Public Sub FunktionFürOrdner(Pfad As String, aktTiefe As Integer)

    in Deiner Zeile 8 kommt dann eben

    VB.NET-Quellcode

    1. FunktionFürOrdner(Verzeichnis, aktTiefe + 1)

    und dann eben noch als erste Zeile Deiner (jetzt) Sub-Prozedur vor Deinem Try:

    VB.NET-Quellcode

    1. If aktTiefe = maxTiefe Then Return

    3 Methoden zur Festlegung von maxTiefe. Du ersetzt das Wort durch ne fixe Zahl (wäre ne "magic number", also eher schlecht, da unflexibel). Oder Du legst maxTiefe als (globale) Variable oder Konstante (Const maxTiefe As Integer = 5) (oder was auch immer Du für ne Tiefe haben willst) fest. Oder noch besser: Du gibst Deiner Sub-Prozedur noch nen Parameter mit, sodass Du dann eben hast:

    VB.NET-Quellcode

    1. Public Sub FunktionFürOrdner(Pfad As String, aktTiefe As Integer, maxTiefe As Integer)


    Aber btw: Wozu gibt es bei Dir ein Try Catch End Try? Wo rechnest Du, könnte was schiefgehen? Und ließe sich nicht ein eventueller Fehler vorher abfangen? Dazu nur von EDF: Warum Try Catch häufig nicht sinnvoll ist
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    VaporiZed schrieb:

    Wozu gibt es bei Dir ein Try Catch End Try? Wo rechnest Du, könnte was schiefgehen? Und ließe sich nicht ein eventueller Fehler vorher abfangen?


    Beim Durchsuchen von Verzeichnissen kann es vorkommen das man keine Rechte hat auf selbige zu zugreifen. Weil das Prüfen von Rechten sch**** an der Stelle ist,geht man dazu über da nen Try/Catch zu platzieren. Wobei der hier dann falsch platziert wäre, da die Schleife nicht weiter laufen würde.
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Wenn unbedingt ein Try verwendet werden soll, dann könnte man gleich das hier nehmen.

    Ersetze:

    VB.NET-Quellcode

    1. Catch ex As Exception
    2. 'mit
    3. Catch ex As UnauthorizedAccessException


    Es wäre auch möglich die Datei- und Verzeichnis-Attribute nach den Rechten abzufragen. Wie weit das jedoch von Nutzen ist, habe ich noch nicht ausprobiert.

    Freundliche Grüsse

    exc-jdbi