Textdatein nach Schlagwort am Zeilenanfang durchsuchen

  • VB.NET

Es gibt 84 Antworten in diesem Thema. Der letzte Beitrag () ist von Dksksm.

    Dan sucht er mir die Dateien nicht raus und schreibt sie nicht in die Listbox.

    Ich verzweifle fast, Arghhhh....:-)

    Wäre einfacher ich könnte den Code den ich jetzt habe reinstellen, also über meinen Rechner.
    Ich mach das auch so, später wenn ich zuhause bin poste ich mal das ganze ding und dann hat auch jeder nen Überblick.
    Aber danke, eben hat es ja so funktioniert. auch viel schneller als den Code den ich zuvor hatte und mit der Progressbar gefällt mir auch sehr gut.
    Hoffe kann den so anpassen dass es klappt.

    vielen vielen Danke bis hier her schonmal

    Wie gesagt, bin von der Nachtschicht zuhause und hier ist mein Code den ich bis jetzt habe:

    VB.NET-Quellcode

    1. Private Sub Scanfiles(targetPath As DirectoryInfo, searchPattern As String)
    2. Dim fiALLFiles As FileInfo() = targetPath.GetFiles("*.dat", IO.SearchOption.AllDirectories)
    3. Dim containingFiles As New List(Of String)()
    4. ProgressBar1.Invoke(New MethodInvoker(Sub() ProgressBar1.Maximum = fiALLFiles.Length))
    5. For Each fi As FileInfo In fiALLFiles
    6. For Each line As String In File.ReadAllLines(fi.FullName)
    7. If line <> "" AndAlso line.TrimStart().StartsWith(searchPattern) Then
    8. containingFiles.Add(Path.GetFileNameWithoutExtension(fi.FullName))
    9. End If
    10. Next
    11. ProgressBar1.Invoke(New MethodInvoker(Sub() ProgressBar1.Increment(1)))
    12. Next
    13. ListBox21.Invoke(New MethodInvoker(Sub() ListBox21.Items.AddRange(containingFiles.ToArray())))
    14. End Sub
    15. Private Sub btnsuchenVS_Click(sender As Object, e As EventArgs) Handles btnsuchenVS.Click
    16. ListBox21.Items.Clear()
    17. Dim searchPattern As String = "75 " & txtsuchenVS.Text
    18. Dim scanThread As New System.Threading.Thread(Sub() Scanfiles(New DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), Pfadprg21)), searchPattern))
    19. scanThread.Start()
    20. MsgBox(searchPattern)
    21. End Sub


    Es funktioniert fast perfekt. Nur sollte er im String die Leerzeichen auch ignorieren. also das in searchPattern auch 7 Leerzeichen stehen könnten anstatt nur eins.
    und wenn ich die anderen Listboxen fülle über andere Pfade ist die Progressbar ja schon fertig bis die Letzte Listbox gefüllt ist. Wie knüpfe ich denn die anderen da dabei?
    Aber das ist eher nebensache, ist nicht wichtig, nur unschön.
    Aber dass er mir die Leerzeichen im String auch verschieden setzt bzw. ignoriert ist unabdinglich.

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

    Du musst das Progressbar.Value dort wo das Maximum der Progressbar gesetzt wird auf 0 stellen. Mit varablen Leerzeichen meinst du das zwischen 75 und dem Rest beliebig viele Leerzeichen stehen können?

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim lineStartPattern As String = "75"
    2. Dim lineSearchPattern As String = textBox1.Text
    3. Dim fileSearchPattern As String = "*.txt"
    4. Dim scanThread As New System.Threading.Thread(Sub() ScanFiles(New DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "testDir")), lineStartPattern, lineSearchPattern, fileSearchPattern))
    5. scanThread.Start()


    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Sucht in allen Dateien mit der Dateiendung .dat nach Zeilen die mit den angegebenen Suchkreterien übereinstimmen
    3. ''' </summary>
    4. ''' <param name="targetPath">DirectoryInfo -Objekt das dass Verzeichniss repräsentiert in dem die Dateien durchsucht werden sollen</param>
    5. ''' <param name="lineStartPattern">Suchbegriff mit dem die Zeile beginnen muss</param>
    6. ''' <param name="lineSearchPattern">Suchbegriff der in der Zeile vorkommen muss</param>
    7. ''' <param name="fileSearchPattern">Suchbegriff für die Dateien die durchsucht werden sollen (DirectroyInfo.GetFiels searchPattern)</param>
    8. Private Sub ScanFiles(targetPath As DirectoryInfo, lineStartPattern As String, lineSearchPattern As String, fileSearchPattern As String)
    9. Dim fiAllFiles As FileInfo() = targetPath.GetFiles(fileSearchPattern, SearchOption.AllDirectories)
    10. Dim containingFiles As New List(Of String)()
    11. progressBar1.Invoke(New MethodInvoker(Function()
    12. progressBar1.Maximum = fiAllFiles.Length
    13. progressBar1.Value = 0
    14. End Function))
    15. For Each fi As FileInfo In fiAllFiles
    16. For Each line As String In File.ReadLines(fi.FullName)
    17. If line <> "" AndAlso line.TrimStart().StartsWith(lineStartPattern) Then
    18. If CheckLine(line, lineStartPattern, lineSearchPattern) Then
    19. containingFiles.Add(Path.GetFileNameWithoutExtension(fi.Name))
    20. End If
    21. End If
    22. Next
    23. progressBar1.Invoke(New MethodInvoker(Function() progressBar1.Increment(1)))
    24. Next
    25. listBox1.Invoke(New MethodInvoker(Function() listBox1.Items.AddRange(containingFiles.ToArray())))
    26. End Sub
    27. ''' <summary>
    28. ''' Prüft ob ein String mit dem enstprechenden Suchkretrium beginnt
    29. ''' </summary>
    30. ''' <param name="line">Zu prüfender String</param>
    31. ''' <param name="lineStartPattern">Suchbegriff mit dem die Zeile beginnen muss</param>
    32. ''' <param name="lineSearchPattern">Der Suchbegriff mit dem der String beginnen muss</param>
    33. ''' <returns>True wenn der String mit dem Suchbegriff beginnt, andernfalls false</returns>
    34. Private Function CheckLine(line As String, lineStartPattern As String, lineSearchPattern As String) As Boolean
    35. ' Entfernt alle Buchstaben am Anfang der Zeile von 0-LineStartPattern -Länge (In diesem Beispiel beträgt die Länge 2 da lineStartPattern 75 ist)
    36. line = line.Remove(0, lineStartPattern.Length)
    37. ' Nun wird wieder mit TrimStart jedes Leerzeichen am Anfang des strings entfernt und geprüft ob der string mit lineSearchPattern (== TextBox1.Text) beginnt ist dem so wird True zurück gegeben
    38. Return line.TrimStart().StartsWith(lineSearchPattern)
    39. End Function


    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Fakiz“ ()

    Danke dir.
    aber jetzt entfernt er aus dem String nicht die Leerzeichen am Anfang der Zeile, obwohl .Trimstart angewendet wird. Alles andere passt von der Suche her.
    und er zeigt er mir an dass was mit dem Aufruf der Funktion nciht stimmt. Ich müsste eine AS-Klausel
    hinzufügen.

    VB.NET-Quellcode

    1. Private Sub ScanFiles(targetPath As DirectoryInfo, lineStartPattern As String, lineSearchPattern As String, fileSearchPattern As String)
    2. Dim fiAllFiles As FileInfo() = targetPath.GetFiles(fileSearchPattern, SearchOption.AllDirectories)
    3. Dim containingFiles As New List(Of String)()
    4. ProgressBar1.Invoke(New MethodInvoker(Function()
    5. ProgressBar1.Maximum = fiAllFiles.Length
    6. ProgressBar1.Value = 0
    7. End Function))
    8. For Each fi As FileInfo In fiAllFiles
    9. For Each line As String In File.ReadAllLines(fi.FullName)
    10. line=line.replace(" ","")
    11. If line <> "" AndAlso line.TrimStart().StartsWith(lineStartPattern) Then
    12. If CheckLine(line, lineStartPattern, lineSearchPattern) Then
    13. containingFiles.Add(Path.GetFileNameWithoutExtension(fi.Name))
    14. End If
    15. End If
    16. Next
    17. ProgressBar1.Invoke(New MethodInvoker(Function() ProgressBar1.Increment(1)))
    18. Next
    19. ListBox21.Invoke(New MethodInvoker(Sub() ListBox21.Items.AddRange(containingFiles.ToArray())))
    20. End Sub


    wenn ich in dem Code Funktion durch Sub ersetzt macht er es.

    edit:

    VB.NET-Quellcode

    1. line=line.replace(" ","")

    habe ich auch versucht, aber das ändert nichts an der Situatuion dass er mir nciht die Leerzeichen vor lineStartPattern entfernt.

    jemand ne idee?

    Edit 2:

    Ich hatte das

    VB.NET-Quellcode

    1. line=line.replace(" ","")
    nur falsch gesetztz, hab es oben im Code auch angepasst.

    so funktioniert es bestens. bis auf die Progressbar halt. Die läuft zwar aber endet nicht wenn das Prg. fertig ist sondern vorher schon.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Gottric“ ()

    Hallo Leute,
    zum Abschluss noch einmal den fertigen Code, habe alle Probleme gelöst und eure Vorschläge umsetzten können auf meine Anwendung.

    VB.NET-Quellcode

    1. Private Sub btnsuchen_Click(sender As Object, e As EventArgs) Handles btnsuchen.Click
    2. System.Threading.Thread.Sleep(100)
    3. If txtsuchen.TextLength = 4 Then
    4. If rbtn21.Checked = True Then
    5. ListBox21.Items.Clear()
    6. ProgressBar1.Value = 0
    7. Dim fInfo21 = New IO.DirectoryInfo(Pfadprg21).GetFiles("*.dat", IO.SearchOption.AllDirectories)
    8. ProgressBar1.Invoke(New MethodInvoker(Sub() ProgressBar1.Maximum = fInfo21.Length))
    9. For Each fi21 In fInfo21
    10. For Each line In IO.File.ReadAllLines(fi21.FullName)
    11. Dim parts = line.Split(New Char() {}, StringSplitOptions.RemoveEmptyEntries)
    12. line = line.Replace(" ", "")
    13. If line.StartsWith("75" & txtsuchen.Text) Then
    14. ListBox21.Items.Add(fi21.Name.Replace(fi21.Extension, ""))
    15. Exit For
    16. End If
    17. Next
    18. ProgressBar1.Invoke(New MethodInvoker(Sub() ProgressBar1.Increment(1)))
    19. Next
    20. End If



    Thema kann geschlossen werden.
    Die Benennung solltest du nochmal überarbeiten.
    Ich habe einen interessanten Link dazu in Beitrag 24 gepostet.

    Das Thema kannst du selbst erledigt markieren, doppelklicke das kleine rote Viereck, rechts neben dem Threadtitle.
    Ich habe deine code mal überarbeitet und kommentiert:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ' Das ganze im Button.Click Event zu erledigen ist unflexibel ! Daher das ganze als eigenständige Methode.
    2. Private Sub SearchText(ByVal text As String)
    3. ' System.Threading.Thread.Sleep(100)
    4. ' Mehr als redundant. ^^
    5. ' If txtsuchen.TextLength = 4 Then
    6. ' If rbtn21.Checked = True Then
    7. ' "= True" ist redundant, "If RadioButton1.Checked" bedeutet schon Ist Gecheckt", für die Abfrage ungecheckt, dann "If Not RadioButton1.Checked" nutzen.
    8. If TextBoxSearchPattern.TextLength = 4 AndAlso RadioButton1.Checked Then
    9. ' Beide If Blöcke können zusammengefast werden.
    10. ListBoxSearchTextResult.Items.Clear()
    11. ProgressBarSearchText.Value = 0
    12. Dim files = New IO.DirectoryInfo(text).GetFiles("*.dat", IO.SearchOption.AllDirectories)
    13. ProgressBarSearchText.Invoke(New MethodInvoker(Sub() ProgressBarSearchText.Maximum = files.Length))
    14. For Each fi In files
    15. ' For Each "Datatype FileInfo", sollte auch sofort erkennbar sein, daher "fi" als Variablenname.
    16. For Each line In IO.File.ReadAllLines(fi.FullName)
    17. ' Hier ist es ähnlich, da hier die Methode .ReadAllLines verwendet wird, sollte auch das sofort erkennbar sein.
    18. 'Dim parts = line.Split(New Char() {}, StringSplitOptions.RemoveEmptyEntries)
    19. ' Redundant.
    20. line = line.Replace(" ", "")
    21. If line.StartsWith("75" & text) Then
    22. ListBoxSearchTextResult.Items.Add(fi.Name.Replace(fi.Extension, ""))
    23. Exit For
    24. End If
    25. Next
    26. ProgressBarSearchText.Invoke(New MethodInvoker(Sub() ProgressBarSearchText.Increment(1)))
    27. Next
    28. End If
    29. End Sub
    30. Private Sub ButtonSearch_Click(sender As Object, e As EventArgs) Handles ButtonSearch.Click
    31. SearchText(TextBoxSearchPattern.Text)
    32. End Sub


    Was das benennen betrifft, wirst du deine eigenen Stil entwickeln.
    Ich z.B. schreibe alles aus (z.B. ButtonClose), man kann aber auch abkürzen (z.B. btnClose), wird in den offiziellen Richtlinien sogar empfohlen.

    PS: Ist dir der Vorschau Button, noch nicht aufgefallen, du hast schon wieder ein End Sub verschluckt !? :D

    Gottric schrieb:

    Thema kann geschlossen werden.
    Wenn ich mir jetzt deinen Code ansehe, fällt mir auf, dass Zeile #13 vollkommen unnötig ist (das war einmal ein Vorschlag von mir...)
    Du liest alle Zeilen der Datei sofort ein ReadAllLines - da wäre es schon besser, du liest sie einzeln hintereinander ein ReadLines.
    Wenn du da bei einer Zeile fündig geworden bist, kannst du sofort aus der Schleife springen - das bringt dir sicher Performance...
    Wie schon gesagt: richtige Benennung der Controls etc.
    Hallo, ich wollte dieses Thema wieder aufgreifen um meine Anwendung schneller zu machen.
    Vom logischen her macht es ja sinn nicht die komplette Textdatei immer einzulesen.
    wie bewerkstellige ich es denn dass die suche abgebrochen wird nach dem er in einer Datei den gesuchten Begriff gefunden hat?
    Wenn ich es in

    VB.NET-Quellcode

    1. ReadLines
    ändere sagt er mir ReadLines wäre kein Member von File.

    das ist der feritge Code der auch wie gewünscht funktioniert. nur halt sehr langsam für meine Begriffe.

    VB.NET-Quellcode

    1. If rbtn21.Checked = True Then
    2. ListBox21.Items.Clear()
    3. ProgressBar1.Value = 0
    4. Dim fInfo21 = New IO.DirectoryInfo(Pfadprg21).GetFiles("*.dat", IO.SearchOption.AllDirectories)
    5. ProgressBar1.Maximum = fInfo21.Length
    6. For Each fi21 In fInfo21
    7. For Each line In IO.File.ReadAllLines(fi21.FullName)
    8. line = line.Replace(" ", "")
    9. If line.StartsWith("75" & txtsuchen.Text) Then
    10. ListBox21.Items.Add(fi21.Name.Replace(fi21.Extension, ""))
    11. Exit For
    12. End If
    13. Next
    14. ProgressBar1.Increment(1)
    15. Next
    16. If ListBox21.Items.Count() = 0 Then
    17. ListBox21.Items.Add("Prg. nicht verwendet!")
    18. End If
    19. End If


    Vielleicht hat ja jemand ne Idee?
    Danke
    Geschwindigkeit ist immer relativ. Wieviel Dateien in welcher Zeit werden verarbeitet?

    Multithreading könnte hier noch was an Zeit raus holen. Hab mal was ähnliches gemacht. Mit Multithreading wars 50% schneller (hab's gemessen).
    "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
    Auf meinem Rechner zuhause brauche ich für einen Suchlauf durch ca. 3000 Textdatein mit je 5- manchmal auch 200 Zeilen(ist von Datei zu Datei unteschiedlich) ungefähr 10sec. auf der Arbeit, wo ich das Tool eigentlich brauche, dauert es über das Netzwerk wo es zugreift schonmal bis zu 40sec. kann natürlich auch am Netzwerk liegen. ist nicht das schnellste :)

    Gottric schrieb:

    (...)bis zu 40sec. kann natürlich auch am Netzwerk liegen(...)


    Naja, ~10 sec lokal find ich jetzt nicht sonderlich tragisch. Immerhin müssen 3000 Dateien geöffnet und geprüft werden. Übers Netzwerk ist halt langsamer da weißte ja woher das kommt.

    Wie gesagt, Multithreading hat bei mir bei ähnlichem Vorhaben eine Zeitersparnis gebracht von 15 auf 7 Minuten runter ;)
    "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

    Gottric schrieb:

    VB.NET-Quellcode

    1. For Each line In IO.File.ReadAllLines(fi21.FullName)
    2. line = line.Replace(" ", "")
    3. If line.StartsWith("75" & txtsuchen.Text) Then

    machst Du

    VB.NET-Quellcode

    1. For Each line In IO.File.ReadLines(fi21.FullName) ' "All" weg
    2. If line.TrimStart().StartsWith("75" & txtsuchen.Text) Then
    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
    wie ich in post 70 schon geschrieben habe sagt er mir ReadLines ist kein Member von File. Das hatt ich natürlich schon versucht.
    aber wenn @mrMo sagt das der zeitaufwand gerechtfertigt, bzw. I.O. ist für das was er zu leisten hat. hat sich das ganze Thema ja geklärt. es funktioniert ja alles wie es soll. dachte nur mein Code wäre was falsch weil es halt 10sec. dauert.
    trotzdem danke für eure hilfe

    Gottric schrieb:

    ReadLines ist kein Member von File.
    Bei mir schon:
    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!