StreamReader - von bestimmter Zeile aus bis zum Ende lesen

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    StreamReader - von bestimmter Zeile aus bis zum Ende lesen

    Huhu :)

    Ich erkläre einfach mal was ich vor habe, damit ihr wisst worum es geht:
    Ich bin dabei ein Programm zu schreiben, dass Informationen aus einer Log-File (Textdatei) lesen muss. Es soll jede Zeile ausgelesen und verarbeitet werden.
    Das komplizierte daran ist, dass sich diese Datei alle paar Millisekunden ändert und mit jedem Eintrag größer wird, sodass ich nach einer Stunde eine riesige Menge an Daten zu verarbeiten habe.

    Mein Code sieht bisher so aus:

    VB.NET-Quellcode

    1. If My.Computer.FileSystem.FileExists(logfile) Then
    2. If Not IsFileInUse(logfile) = True Then
    3. Dim i As Integer = 0
    4. Using sr As New IO.StreamReader(logfile)
    5. Dim line As String
    6. line = sr.ReadLine
    7. Do While (Not line Is Nothing)
    8. list.Add(line)
    9. i = i + 1
    10. line = sr.ReadLine
    11. Loop
    12. End Using
    13. End If
    14. End If


    Damit wird erst ein mal jede Zeile in eine Liste geladen die ich benötige um alle bisherigen Einträge zu verarbeiten. (Verarbeiten bedeutet in diesem Fall bestimmte Aktionen aus zu führen die vom Zeileninhalt abhängig sind.)
    Jetzt möchte ich es aber hin bekommen, dass die Einträge die jede Sekunde dazu kommen in die Liste geladen werden, dazu müsste ich den Stream bei jedem Lesen zu der Zeile springen lassen, die ich zuletzt ausgelesen habe. Nur ich weiß nicht wie ich das hin bekommen soll.

    Am Ende, soll meine Liste gesplittet werden, alles was verarbeitet wurde kommt raus und was noch nicht verarbeitet wurde, steht in der Liste, in der über einen Timer alle 100 ms die neuen Zeilen aus der Log-File geladen werden. Dazu müsste ich aber wissen, wie ich jedes mal in die Textdatei zu der Zeile springe, die bei mir als Letztes eingelesen wurde, damit ich nur die neuen Einträge bekomme.

    Ich hab hier im Forum über die SuFu ein paar Threads gelesen, in denen es aber nur darum ging eine spezielle Zeile aus zu lesen. Habe aber noch nichts darüber heraus gefunden wie man zu einer Zeile springt und bis zum Ende der Datei, Zeile für Zeile aus liest. Kann mir da jmd. sagen wie ich das hin bekomme?

    Ich bedanke mich schon mal im Voraus für alle Antworten^^

    LG

    VB1963 schrieb:

    Willkommen im Forum :)
    Wenn dieses LogFile in weiterer Folge nicht mehr gebraucht wird, könntest du gie eingelesenen Zeilen aus dem LogFile löschen.
    Dann hast du immer nur ungelesene Zeilen im LogFile...
    Danke :)
    Ich würde die Log-File gerne behalten, muss aber nicht sein.
    Da sie aber alle paar ms von einem Programm neu beschrieben wird, kann ich sie nicht löschen, weil die Rechte fehlen. Deshalb prüfe ich vor dem Lesen jedes mal ob die Datei gerade von einem anderen Programm benutzt wird.

    Kilian_98 schrieb:

    Setze deine Variable i global (außerhalb eines subs) und
    sage dem Programm, es soll die zeile nur auslesen, wenn die aktuelle
    Zeile größer als i ist (du brauchst eine zweite variable für die Zählung der Zeile)

    Mfg
    Ja, die Idee hatte ich schon. Aber bei ner mio Einträge würde das ziemlich lange dauern bei jeder Zeile den Vergleich durch zu führen, oder?^^
    Willkommen im Forum. :thumbup:

    Perzeus schrieb:

    VB.NET-Quellcode

    1. If Not IsFileInUse(logfile) = True Then
    halte ich trotzdem für problematisch, wenn der Gegenpart sich nicht ebenso absichert.
    Eine solche Datenflut ist iwie nicht ganz nützlich, wenn sie in absehbarer Zeit die Festplatte zumüllt.
    Lässt sich da iwie Einhalt gebieten?
    Wie wäre es, wenn Du den Logfile, wenn er nicht im Zugriff ist, umbenennst, dann kannst Du sicher sein, dass während Deines Lesezugriffs auf ihn kein Schreibzugriff getätigt wird.
    Und wenn Du fertig bist, könntest Du ihn ggf. löschen. 8o
    -----
    Es ist nicht erforderlich, den kompletten Post über dem eigenen zu löschen, das wird hier nicht gern gesehen.
    Wenn u jemanden gezielt ansprechen willst, schreib
    @ USERNAME :
    (ohne Leerzeichen) und der User bekommt einen Hinweis auf ein Zitat und wird direkt zu diesem Post gelenkt.
    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!
    @Kilian_98:
    Ja, das erfordert wieder das ich die Datei kopiere und hinterher lösche, was von Programm das die Log-File erstellt verhindert wird..

    @RodFromGermany:
    Naja, Log-File ist Log-File, die enthält nun mal alle möglichen Infos. Sie wird von einem Programm erstellt auf das ich keinen Zugriff habe und das sie mit der Zeit riesig wird, hab ich mir ja nicht ausgedacht. Sie wird aber regelmäßig (nach einem bestimmten Zeitraum) vom Programm selber wieder gelöscht bzw. archiviert, sodass die Datei dann regelmäßig neu erstellt wird.

    Naja, ich versuch es mal mit Umbenennen und anschließend Backup erstellen. Fänd es nur schöner wenn ich einfach mit dem Stream-Reader an eine bestimmte Zeile springen und so weiter machen kann^^
    Danke für die Antworten :)

    LG
    ich hab jetzt mehrere Probleme gelesen:
    1. zeilenweises einlesen - gelöst
    2. jede Zeile einer List(Of String) zufügen - keine gute Idee
    3. bestimmte Zeilen verarbeiten - gelöst
    4. die verarbeiteten Zeilen gesondert wegschreiben - ungelöst
    5. das LogFile manipulieren - keine gute Idee
    6. im LogFile an eine bestimmte Stelle springen - ungelöst
    ist das so weit richtig oder kommt noch was dazu?

    nach meim Verständnis bleiben also Themen: bestimmte Zeilen wegschreiben und an eine Stelle springen.
    Das Wegschreiben kriegst du hin?

    Dann wäre noch das an eine Stelle springen interessant. Lösung ist prinzipiell einfach: Merk dir, wo du vorher warst :D
    Praktisch ists kniffliger, denn mann müsste die Position des BaseStreams des StreamReaders dazu benutzen, und das fiese ist, dessen Position rückt nicht zeilenweise vor, sondern Blockweise.
    Ja, deine Liste ist soweit richtig^^
    Bestimmte Zeilen aus der Liste entfernen würde ich mit list.RemoveAt(x) bzw. list.Remove(line) machen.

    Das mit dem Springen an eine bestimmte Stelle ist das Eigentliche (Wie auch der Titel sagt) das ich nicht hin bekomme..
    Dadurch, dass ich am Anfang die komplette Log-File (einmal) in die Liste lade, weiß ich ja durch Mitzählen bei welcher Zeile ich in der Textdatei bin also weiß ich ja wo ich war. Nur wie ich jetzt den Stream dazu bringe mit meiner Schleife nicht am Anfang der Textdatei sondern bei Zeile x weiter zu machen, weiß ich nicht.

    Ich bin jetzt auf die Idee gekommen es so zu lösen:


    VB.NET-Quellcode

    1. Using sr As New IO.StreamReader(logfile)
    2. Dim x as String 'Die Position die ich mir gemerkt habe, angenommen ich hatte vorher bis Zeile 200 gelesen, dann ist der Wert jetzt 200
    3. Dim line As String
    4. line = sr.ReadLine
    5. Do While (Not line Is Nothing)
    6. If i > x then 'Hier springe ich dann erst ein, sobald ich bei Zeile 201 bin
    7. list.Add(line)
    8. i = i + 1 'i wird weiterhin hoch gezählt, da die Log-File ja gleich bleibt, ist aber jetzt global deklariert
    9. line = sr.ReadLine
    10. Else 'Ich springe also die ganze Zeit in die Else, bis ich bei Zeile 200 bin, wo ich zuletzt aufgehört habe, bevor ich die Datei zum Aktualisieren neu eingelesen habe
    11. line = sr.ReadLine
    12. End If
    13. Loop
    14. End Using


    Würde bedeuten: Ich lese einfach von Anfang bis Zeile x jede Zeile ein, mache mit ihr aber nichts, erst wenn ich an der Position angekommen bin, die ich mir gemerkt habe, wird weiter in die Liste geladen.
    Parallel dazu wird die Liste immer kleiner, da ich diese Eintrag für Eintrag mit einem weiterem Loop über eine Case-Abfrage verarbeite.
    Die Rechenzeit die gebraucht wird um jedes mal eine Zeile zu lesen, mit dieser aber nichts zu machen, sollte nicht all zu hoch sein oder?

    Ich bin gerade nicht am PC zuhause, deswegen kann ich es nicht testen, aber es sollte funktionieren, wie schnell das ist weiß ich aber noch nicht..

    LG

    Perzeus schrieb:

    Bestimmte Zeilen aus der Liste entfernen würde ich mit list.RemoveAt(x) bzw. list.Remove(line) machen.
    wozu soll die Liste gut sein?
    Lass die weg.
    Wenn eine Zeile zur Verarbeitung kommt, dann verarbeite sie. (wobei wegschreiben auch eine Verarbeitung ist).
    Tu sie nicht in eine Liste, und lösch sie nachher wieder.

    Zum wiederauffinden gemerkter Lesepositionen: Beispiele der Log-Zeilen wäre nun hilfreich.

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

    Mhh ich glaub ich hab vergessen was wichtiges zu erwähnen: Die Infos die ich verarbeite, sollten so schnell es geht zu der Zeit verarbeitet werden, zu der die Info in die Log-File geschrieben wird.
    Also (nur als Beispiel) angenommen die Log-File ist der Chat-Log von einem IRC. Und ich schreibe in den IRC Befehle. Diese erscheinen Millisekunden danach in der Log-File die ich auch Millisekunden danach in meinem Programm einlese.

    Das Problem ist, wenn ich bei 1.000 Zeilen, jede Zeile sofort verarbeite, hängt er irgend wann nach.
    Wenn ich aber parallel zum Einlesen, was ja ziemlich schnell geht, die ganzen Items aus der Liste einzeln abarbeite geht es schneller. Da ich parallel mehrere Zeilen auf einmal aus der Liste verarbeiten kann.
    Also ich hab es jetzt gelöst indem ich die Datei umbenannt habe. Dann Zeile für Zeile aus gelesen und direkt verarbeitet habe und nach dem ich durch bin, die Datei gelöscht habe. Anstatt sie zu löschen, könnte ich auch den Inhalt jedes mal in eine Backup Datei schreiben, somit würde nichts verloren gehen. Problem ist also gelöst, auch ohne das ich im Stream rum springen muss :D

    Danke an Alle die geholfen haben^^
    also die Log-Datei selbst benennst du um?

    jo - lustige Idee: Das Logging-Tool erstellt dann wohl automatisch eine neue, und die ist dann auch nicht mehr so pervers fett :thumbup:

    Täte mir höchstens Sorgen machen, was ist, wenn das Logging-Tool grad reinschreiben will, während du umbenennst (race-condition).

    ErfinderDesRades schrieb:

    also die Log-Datei selbst benennst du um?
    Jap, das hat jetzt mehrfach so funktioniert.

    ErfinderDesRades schrieb:

    Täte mir höchstens Sorgen machen, was ist, wenn das Logging-Tool grad reinschreiben will, während du umbenennst (race-condition).
    Naja, wenn das passieren wird, meckert er höchstens weil er keine Rechte hat, da die Datei gerade beschrieben wird. In dem Fall bekomme ich nen Fehler, den ich wahrscheinlich ignorieren und es noch mal versuchen kann, muss mir da nur die Fehlerbehandlung mal ansehen^^