Textdateien in einem Verzeichnis nach Wörtern durchsuchen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von EaranMaleasi.

    Textdateien in einem Verzeichnis nach Wörtern durchsuchen

    Hallo,

    ich habe einen Ordner mit mehreren Textdateien (Anzahl & Name der Dateien immer unterschiedlich) & eine Textbox (Suchfeld).

    Ich würde gern alle Textdateien in dem Verzeichnis nach bestimmten Wörtern (mit Textbox.Textchanged) durchsuchen & wenn irgendeine der Dateien im Verzeichnis das gewünschte Wort enthält, dann soll eine bestimmte Aktion ausgeführt werden.

    Wenn in der Textbox zwei (oder drei, vier, ....) Wörter eingegeben werden ( Bsp. "BMW Sitzheizung" // Worttrennung auch nur mit Leerzeichen) , soll er in dem Verzeichnis erst nach dem ersten Wort suchen, wenn gefunden, dann nach dem zweiten Wort, wenn gefunden dann Aktion ausführen, sonst nichts machen.

    Das Problem ist, die einzelnen Wörter können in verschiedenen Text-Dateien sein...

    Bekomme es einfach nicht hin....



    Bedanke mich recht herzlich im Voraus

    Grüße
    Also fassen wir mal kurz zusammen:
    1. Du hast eine Textbox in der Wörter eingetragen werden, nach denen Gesucht werden soll
    2. Du hast einen haufen Dateien
    3. Hier bin ich gerade leicht verwirrt... willst du alle Dateien haben, in denen 1 oder mehr Wörter vorkommen? oder willst du nur Dateien haben, in denen alle Wörter vorkommen?

    Ich gehe mal davon aus, dass du alle Dateien haben möchtest, in denen mind. 1 Wort aus der Textbox vorkommt.

    TextChanged finde ich hierbei ein furchtbar unpassendes Event. Jedesmal wenn man etwas eintippt, wird dabei ein Ordner mit evtl. 2 Millionen Dateien von jeweils mehreren Gigabyte an Größe nach einem evtl. unfertigen Wort durchforstet. Ich weiß, das ist vermutlich fernab vom eigentlichen Usecase, doch die möglichkeit besteht.

    Auch finde ich es recht unperformant, dass man die Dateien mehrmals durchläuft, wenn man am Ende einfach nur alle Dateien haben möchte, die mind. ein Wort aus der Textbox besitzen.

    Mein vorschlag wäre, versehe die Maske auf der sich die TextBox befindet mit einem Button Suchen, der dann die eigentliche Suchaktion auslöst. Nun nimmst du dir erstmal den Text der Textbox her und splittest den am Leerzeichen. Dadurch bekommst du dann ein Array vom Typ String. Als nächstes holst du dir die Dateien, und gehst die, entweder so wie du es gemacht hast mit ReadLines durch, oder aber holst dir gleich den ganzen Text rein, sofern die Größe der Dateien überschaubar ist. Und jetzt rufst du .Contains für jedes Element in deinem Array auf. Sollte nun also eine Datei das gewünschte Wort beinhalten kannst du, je nachdem was du brauchst, die FileInfo Instanz, oder auch nur den Pfad in einer separaten Liste abspeichern.

    Bist du dann mit allen Dateien durch, kannst du die nächste Aktion starten, und die Liste mit den Dateien der Funktion übergeben, oder was auch immer als nächstes passiert.
    Wenn mehrere Wörter im Suchfeld eingegeben werden, soll die Aktion auch nur ausgeführt werden, wenn in irgendeiner der ganzen Dateien im Verzeichnis alle gesuchten Wörter enthalten sind.

    Bsp:

    Ausstattung.txt (Inhalt der Text-Datei: Sitzheizung, Navigationssystem, Kamera)
    FZG-Daten.txt (Inhalt der Text-Datei: BMW, 320d Touring, Kombi)

    Suchfeld (Textbox): Sitzheizung Kombi

    Jetzt soll die Aktion ausgeführt werden, da das erste Wort in Ausstattung.txt enthalten ist und das zweite Wort in FZG-Daten.txt

    ILLEX schrieb:

    wenn in irgendeiner der ganzen Dateien im Verzeichnis alle gesuchten Wörter enthalten sind

    Dein Beispiel wiederspricht sich aber gerade mit deiner Aussage.
    Du sagst, die nachfolgende Aktion soll ausgeführt werden, wenn:
    in EINER Datei ALLE gesuchten Wörter vorhanden sind.

    Dein Beispiel hingegen zeigt jedoch, dass die beiden Suchwörter "Sitzheizung" und "Kombi" Jeweils in einer anderen Datei auftauchen, was deiner Aussage nach nicht zum Auslösen der Aktion führen würde.
    hier ein Bsp. mit Regex und der suche mit mehreren Wörter
    ich lade die txt in eine Richtextbox, das ergebnis siehst du in eine Listbox

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Public Class Form1
    3. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    4. RichTextBox1.LoadFile("E:\TestFolder\Ausstattung.txt", RichTextBoxStreamType.PlainText)
    5. End Sub
    6. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    7. FindLines()
    8. End Sub
    9. Private Sub FindLines()
    10. Dim lines As New List(Of String)
    11. lines = RichTextBox1.Lines.ToList
    12. 'Regex Pattern = Suchwörter getrennt durch |
    13. Dim s1 As String = " Sitzheizung|Navigationssystem|Kamera"
    14. For i As Integer = lines.Count - 1 To 0 Step -1
    15. If Regex.IsMatch(lines(i), s1) Then
    16. 'zb. Aktion Zeile entfernen = lines.RemoveAt(i)
    17. ListBox1.Items.Add(lines(i) & " (Gefunden in Zeile =" & i + 1 & ")")
    18. End If
    19. Next
    20. RichTextBox1.Lines = lines.ToArray
    21. End Sub
    22. End Class
    @ILLEX Okay, damit lässt sich arbeiten. Und nun verstehe ich auch deinen Ansatz ;)

    Also was du brauchst ist nach wie vor das Array (oder eine Liste) in dem du den Inhalt der TextBox reinsplittest.

    Nun gehst du die Dateien nach und nach durch, und schaust, ob die Wörter in der Liste in der Datei auftauchen. Ist dem der Fall, löschst du das gefundene Wort aus der Liste. Sobald die Liste Leer ist, brichst du die Schleifen ab, und kannst deine Aktion durchführen.
    Damit würde aber eine Datei, die zwar mindest einen der Suchbegriffe enthält nicht mehr gefunden werden, wenn diese Suchbegriffe wegen bereits gefundener Treffer nicht mehr in der Suchliste sind....
    Das kann sein, dass das nicht Zielführend ist. Um das zu beurteilen muss die Aufgabenstellung konkretisiert werden.
    Was lediglich klar geworden ist, dass alle Suchbegriffe wenigstens einen Treffer landen müssen, damit eine folgende Aktion (die nicht weiter besprochen wurde) ausgelöst wird.
    Auch hier wäre es aber nicht unwichtig zu wissen, was die Aktion den ist, möglicherweise benötigt man die Suchliste hier noch einmal.
    @EaranMaleasi
    Kannst du mir evtl nochmal weiterhelfen? Ich bekomme es einfach nicht hin...

    Meine Form:

    - Textbox1
    - Button1

    Textdateien in einem bestimmten Ordner (Anzahl immer unterschiedlich):

    artikel1.txt (Inhalt: Banane)
    artikel2.txt (Inhalt: Apfel)
    artikel3.txt (Inhalt: Birne)
    ....

    Wenn Button1 gedrückt wird, soll geprüft werden, ob alle Artikel vorhanden sind.

    Bsp 1:
    Textbox1.Text = "Banane Birne"
    MsgBox: Alle Artikel vorhanden

    Bsp 2:
    Textbox1.Text = "Banane Zitrone"
    Nichts tun (da Zitrone fehlt)

    Bsp 3:
    Textbox1.Text = "Banane"
    MsgBox: Alle Artikel vorhanden


    Komme einfach nicht an die Lösung....
    Okay, Zeit für etwas Fließcode.

    Als erstes, splitte den Inhalt der Textbox in ein Array searchObjects.
    Dazu legst du noch eine Liste vom Typ String namens foundObjects, und ein boolean allElementsFound mit dem Wert false an.

    Nun nimmste eine Schleife, und iterierst über die Dateien.
    Als erstes überprüfst du ob die anzahl der Elemente in searchObjects mit der in foundObjects übereinstimmt. Falls ja, setzt du allElementsFound auf true und brichst die Schleife ab.

    Als nächstes ließt du nun die Datei mit File.ReadAllText ein, und gehst nun in eine weitere Schleife, die über searchObjects iteriert. In dieser Schleife prüfst via .Contains ob der eingelesene Text den String aus dem Array beinhaltet. Wenn ja, füge den Text foundObjects hinzu.

    Nach den Schleifen prüfst du nun, ob allElementsFound auf true gesetzt wurde, und fährst dann entsprechend fort.