Prüfen ob die letzten beiden Zeicheneiner Textdatei ein CRLF ist

  • Hallo zusammen,

    irgendwie stehe ich auf dem Schlauch mit dem o.g. Problem.
    Für eine Weiterverarbeitung des entsprechenden Files, muss ich sicherstellen,
    dass das Ende der Datei eine Zeile ist ohne abschliesenendes CRLF.
    meistens jedoch ist sind die beiden letzten Zeichen ein CRLF (leider aber nicht immer)

    z,B,
    hans,wurst,1234,ffm CRLF
    angela,mett,4567,ffm CRLF
    blut,wurst,8910,ffm CRLF

    Was ich hinbekomme:
    mittels 'FileGetPos' kann ich auf die Postion des letzten Zeichens schliessen
    wie ich (ohne Prüfung) die beiden letzten Zeichen lösche, bekomme ich auch mittels 'StringTrimRight' hin

    Aber wie kann ich den 'Inhalt' des letzten bzw. vorletzten Zeichens ermitteln, um dann ggf. diese zu löschen


    Spoiler anzeigen


    Example()

    Func Example()
    ; Create a constant variable in Local scope of the filepath that will be read/written to.
    Local Const $sFilePath = "c:\temp\___000\Test_CRLF.csv"

    Local $hFileOpen = FileOpen($sFilePath)
    ; Check file position and try to read contents for current position.
    MsgBox($MB_SYSTEMMODAL, "", "Position: " & FileGetPos($hFileOpen))

    ; Now, adjust the position to the beginning.
    FileSetPos($hFileOpen, 0, $FILE_END)

    ; Check file position and try to read contents for current position.
    MsgBox($MB_SYSTEMMODAL, "", "Position: " & FileGetPos($hFileOpen))
    MsgBox($MB_SYSTEMMODAL, "", "Position: " & FileGetPos($hFileOpen)-1)

    ; Close the handle returned by FileOpen.
    FileClose($hFileOpen)

    EndFunc ;==>Example


    Wäre für den ein oder anderen Tip dankbar


    mfg
    ugt100

  • Mit FileReadLine die letzte Zeile auslesen, mit StringReplace dann das CRLF ersetzen und mit FileWriteLine wieder zurück schreiben.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Dein Ansatz mit FileSetPos war doch gar nicht mal so schlecht.
    Bisschen weiter ausgebaut wäre folgendes ein Ansatz:

    [autoit]

    #include <FileConstants.au3>

    [/autoit][autoit][/autoit][autoit]

    ; Datei öffnen
    $h_File = FileOpen("Test.txt", 0)

    [/autoit][autoit][/autoit][autoit]

    ; Dateizeiger auf zwei Zeichen vor dem Ende setzen:
    FileSetPos($h_File, -2, $FILE_END)

    [/autoit][autoit][/autoit][autoit]

    ; Letzten zwei Zeichen auslesen:
    $s_Text = FileRead($h_File)

    [/autoit][autoit][/autoit][autoit]

    ; Check auf CRLF:
    If $s_Text == @CRLF Then MsgBox(0,"", "Letzte zwei Zeichen sind CRLF")

    [/autoit][autoit][/autoit][autoit]

    ; Datei wieder schließen:
    FileClose($h_File)

    [/autoit]
  • Alternativ könntest Du zum Abprüfen StringRight verwenden

    Code
    $sString = "hans,wurst,1234,ffm CRLF"
    If StringRight($sString, 4) = "CRLF" Then $sString = StringTrimRight ($sString, 4)
    MsgBox(0,"",$sString)

    Ich weiß gar nichts.

  • Guten Morgen zusammen,

    danke erstmal für die Tips. Damit ist es mir gelungen mein 'Problem' zu lösen.

    hier die meinige Umsetzung

    Spoiler anzeigen

    $sMessage = "Bitte das Quellfile (zwingend Format Textfile) angeben"
    $sSourceCDE = FileOpenDialog($sMessage,@ScriptDir & "\", "Textfile (*.txt;*.csv)",1,"") ;QuellFile angeben für NRF's
    If @error = 1 Then Exit ;Cancel-Button
    $hSourceCDE = FileOpen($sSourceCDE,0) ;File handle lesend öffnen
    FileSetPos($hSourceCDE, -2, $File_End) ;Pointer auf das vorletzte Zeichen der Datei setzen
    $sTextCDE = FileRead($hSourceCDE) ;die letzten beiden Zeichen der Datei einlesen
    If $sTextCDE == @CRLF Then ;auf CRLF prüfen
    FileClose($hSourceCDE) ;File handle schliessen (enthält ja nur die letzten 2 Zeichen)
    $hSourceCDE = FileOpen($sSourceCDE,0) ;File handle erneut lesend öffnen
    $sReadSourceCDE = FileRead($sSourceCDE) ;und Inhalt in Variable übergeben
    FileClose($SourceCDE) ;File handle schliessen
    $sReadSourceCDE = StringTrimRight($sReadSourceCDE,2) ;CRLF entfernen und wieder in Variable übergeben
    $hSourceCDE = FileOpen($sSourceCDE,2) ;File handle (über)schreibend öffnen
    FileWrite($hSourceCDE,$sReadSourceCDE) ;geänderten Inhalt von Variable in handle übergeben ;Inhalt zurückschreiben
    EndIf
    FileClose($hSourceCDE)

    Jetzt erscheint mir das aber doch nicht so optimal - eher suboptimal - was den Code angeht (das mit dem vielen FileOpen/FileClose ...)
    Gibt es aus der Profisciht etwas Eleganteres ?

    Wie gesagt so wi e beschrieben funktioniert es


    Danke an alle und MERCI :thumbup:

  • Hi BugFix,

    da bin ich aber geplättet - an den RegEX Ausdruck habe ich überhaupt nicht gedacht,
    obwohl ich die Aufbereitung im notepad++ genauso mache (schön blöd - ich grrrrr)

    DANKE

    Mfg
    ugt100

  • Jetzt erscheint mir das aber doch nicht so optimal - eher suboptimal - was den Code angeht (das mit dem vielen FileOpen/FileClose ...)
    Gibt es aus der Profisciht etwas Eleganteres ?

    Die Idee, die dahinter steht, ist, gleich mit dem FilePointer weiterzuarbeiten und die Datei einfach um zwei Zeichen zu kürzen.
    Alle anderen hier vorgestellten Lösungen machen prinzipiell folgendes:

    • Datei komplett von der Festplatte in den Arbeitsspeicher einlesen
    • In diesem String die letzten Zeichen raussuchen und mit @CRLF vergleichen
    • Im Positivfall den Gesamtstring um zwei Zeichen kürzen
    • Die alte Datei löschen
    • Eine neue Datei schreiben mit dem, um zwei Zeichen gekürzten, String als Inhalt.

    Das ist die einfachste Lösung wenn deine Dateien klein sind.
    Wenn sie allerdings größer sind ist das absolut suboptimal weil dich eigentlich nur die letzten beiden Zeichen interessieren.
    Daher war mein Vorschlag hierbei mit der Position des File-Pointers zu arbeiten.
    Hierbei werden von der Festplatte tatsächlich nur die letzten zwei Zeichen geladen (statt der gesamten Datei) und im Positivfall kann man einfach die Länge der Datei um zwei Zeichen kürzen ohne dass die restlichen Daten jemals angefasst werden - schneller und effektiver gehts nicht.
    Wie ich mittlerweile herausgefunden habe, habe ich dafür schonmal eine Funktion geschrieben: _FileDeleteLastCRLF().

    Deren Anwendung sollte simpel und selbsterklärend sein.

  • Hallo Aspirin Junkie,

    klingt absolut sinnig was Du zu der Methodik sagst und ist bestimmt auch so etwas wie ein 'Königsweg' (werde ich mir merken) - Danke
    Der Ansat zvom BugFix ist halt einfach so naheliegend, da ich das so in den ersten Zügen genauso gemacht habe
    Notepad++ / Suchen&Ersetzen (unter Anzeige aller Zeichen) ...

    Die Funktion schau ichmir gleich mal näher an
    Merci vielmals

    mfg
    ugt100