Ich habe eine Textdatei in der sind pro Zeile 192 Zeichen gesetzt, nur die letzte, die kann 192 oder weniger Zeilen lang sein.
Wie zähle ich die Zeilen in einer Textdatei, die 192 Zeichen lang sind?
$_zeilen = verwendete Zeilen der Länge 192
Zeilen -1
-
Alina -
29. Oktober 2023 um 12:25 -
Erledigt
-
-
Mit _FileReadToArray() einlesen und dann mit StringLen() jede Zeile zählen.
-
Habe jetzt folgende Lösung geschrieben.
Kann man das oder sollte man das noch ändern / verbessern? "In der Kürze, soll liegen die Würze".
Spoiler anzeigen
Code
Alles anzeigen$Dateipfad = @ScriptDir & "\test.txt" $file = FileOpen($Dateipfad, 0) If $file = -1 Then MsgBox(0, "Fehler", "Die Datei konnte nicht geöffnet werden.") Exit EndIf $Zeilenanzahl = 0 While 1 $Zeile = FileReadLine($file) If @error = -1 Then ExitLoop If StringLen($Zeile) = 192 Then $Zeilenanzahl += 1 EndIf WEnd FileClose($file) MsgBox(0, "Zeilenanzahl", "Die Datei hat " & $Zeilenanzahl & " Zeilen der Länge 192 Byte.")
-
sollte passen
-
Performance ist halt bei Tweaky's erstem Vorschlag besser.
-
sollte passen
Ja, von der Funktion passt es. Es kommen richtige Ergebnisse raus.
Die Variable $Zeilenanzahl ist ja das, was ich brauche.
Hatte erst an Mod 192 gedacht, aber dann doch auf die obere Lsg. gekommen.
Gibt aber bestimmt mehrere Lösungswege. Kürzen kann man bestimmt immer,
wenn es von mir kommt. *fg* -
Performance ist halt bei Tweaky's erstem Vorschlag besser.
Das glaube ich Dir gerne. Aber ist das bei maximal 2.304.000 Byte in der Textdatei (12.000 Zeilen) zu beachten?
-
Da wird es nicht spürbar sein
-
Da wird es nicht spürbar sein
Habe ich mir auch gedacht.
Das Weiterte was ich vor habe, da muss ich wohl drauf achten, was die Performance betrifft. Da sind dann maximal 12.000 Schleifendurchläufe nötig.
Erst mal weiter machen und dann sehen wo der Schuh zu eng ist, wenn es passieren sollte. -
Performance ist halt bei Tweaky's erstem Vorschlag besser.
Mit _FileReadToArray() einlesen und dann mit StringLen() jede Zeile zählen.
Bei der Variante ist die Performance schlechter als in Alinas Variante - zumindest nach meinen Tests (einfach ausführen):
AutoIt
Alles anzeigen#include <String.au3> #include <File.au3> #region create test file Global $N_testfile = 12000 ; number of lines Global $hTestFile = FileOpen("test.txt", 2) For $i = 1 To $N_testfile FileWriteLine($hTestFile, _StringRepeat("o", Random(191,192,1))) Next FileClose($hTestFile) ##EndRegion #region performance comparison Global Const $N = 1e2 ; number of measures Global $iT, $f_Overhead ConsoleWrite(@CRLF & " name time result" & @CRLF & "----------------------------------------------" & @CRLF) ; determine the overhead of loop [and optional other stuff] $iT = TimerInit() For $i = 1 To $N Next $f_Overhead = TimerDiff($iT) ; variant with _FileReadToArray $iT = TimerInit() For $i = 1 To $N Local $aFile, $iCount = 0 _FileReadToArray("test.txt", $aFile) For $j = 1 To $aFile[0] If StringLen($aFile[$j]) = 192 Then $iCount += 1 Next Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\t% 6d\n", "_FileReadToArray", ($iT-$f_Overhead) / $N, $iCount)) ; variant with FileReadLine $iT = TimerInit() For $i = 1 To $N Local $hFile = FileOpen("test.txt", 0), $iCount = 0, $sLine While 1 $sLine = FileReadLine($hFile) If @error = -1 Then ExitLoop If StringLen($sLine) = 192 Then $iCount += 1 WEnd FileClose($hFile) Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\t% 6d\n", "FileReadLine", ($iT-$f_Overhead) / $N, $iCount)) ; variant with FileReadToArray $iT = TimerInit() For $i = 1 To $N Local $iCount = 0 Local $aFile = FileReadToArray("test.txt") For $j = 0 To @extended - 1 If StringLen($aFile[$j]) = 192 Then $iCount += 1 Next Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\t% 6d\n", "FileReadToArray", ($iT-$f_Overhead) / $N, $iCount)) ; variant with StringRegExpReplace $iT = TimerInit() For $i = 1 To $N StringRegExpReplace(FileRead("test.txt"), '(?m)^.{192}$', '') Local $iCount = @extended Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\t% 6d\n\n", "StringRegExpReplace", ($iT-$f_Overhead) / $N, $iCount)) ##EndRegion
Was mich aber viel mehr interessiert:
Ich habe eine Textdatei in der sind pro Zeile 192 Zeichen gesetzt, nur die letzte, die kann 192 oder weniger Zeilen lang sein.
Warum möchtest du die Längen aller anderen Zeilen ermitteln wenn du doch bereits weißt, dass sie immer 192 Zeichen lang sind?!?
Du interessierst dich doch offensichtlich nur für die Länge der letzten Zeile.
Hierfür muss man doch aber gar nicht die ganze Datei durchgehen:
-
Was mich aber viel mehr interessiert :
Warum möchtest du die Längen aller anderen Zeilen ermitteln wenn du doch bereits weißt, dass sie immer 192 Zeichen lang sind?!?
Du interessierst dich doch offensichtlich nur für die Länge der letzten Zeile.
Hierfür muss man doch aber gar nicht die ganze Datei durchgehen:
Falls ich es korrekt verstehe möchte Alina die Anzahl aller Zeilen mit Zeichenlänge 192 ermitteln.
Alle Zeilen - bis auf die letzte - sind immer 192 Zeichen lang.
Es geht, wie Du richtig angeregt hast, also nur um die Zeichenlänge der letzten Zeile.
AutoIt$iLen = StringLen(FileReadLine("test.txt", -1)) MsgBox(0, "", "Länge der letzten Zeile: " & $iLen)
Hiermit wird aber nur die Zeichenlänge der letzten Zeile geprüft - nicht die Anzahl der vorangegangenen Zeilen ermittelt.
Wäre es so nicht besser ? :
AutoIt[... Testdatei generieren] Global $iCountLines, $iT $iT = TimerInit() $iCountLines = _FileCountLines("test.txt") ; Anzahl aller Zeilen in Datei If StringLen(FileReadLine("test.txt", -1)) <> 192 Then $iCountLines -= 1 ; Falls letzte Zeile <> 192 Zeichen, dann abziehen $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%10.6f ms\t% 6d\n", "_FileCountLines", $iT, $iCountLines)) ....
-
Nachtrag :
Ich habe mal eine Zeitberechnung (wie in dem Script von AspirinJunkie ) laufen lassen, allerdings die reale Zeit ohne Berücksichtigung eines Overheads.
Hinzugefügt habe ich die Variante mit _FileCountLines
(Testdatei : 12000 Zeilen , die ersten 11999 Zeilen mit Länge 192, Zeile 12000 (die letzte) mit weniger als 192 Zeichen)
Ergebnis :
Codename time result ---------------------------------------------- _FileCountLines: 97.3117 ms 11999 _FileReadToArray: 140.5026 ms 11999 FileReadLine: 110.7730 ms 11999 FileReadToArray: 70.4800 ms 11999 StringRegExpReplace: 73.0387 ms 11999
Hier das modifizierte Testskript :
Spoiler anzeigen
AutoIt
Alles anzeigen#include <String.au3> #include <File.au3> #Region create test file Global $N_testfile = 11999 ; number of lines with length 192 Global $hTestFile = FileOpen("test.txt", 2) For $i = 1 To $N_testfile FileWriteLine($hTestFile, _StringRepeat("o", 192)) Next ; Write last line (Line 12000) - can be less then 192 : FileWriteLine($hTestFile, _StringRepeat("o", 191)) FileClose($hTestFile) ##EndRegion #Region performance comparison Global Const $N = 1e2 ; number of measures Global $iCount, $iT ConsoleWrite(@CRLF & " name time result" & @CRLF & "----------------------------------------------" & @CRLF) ; variant with _FileCountLines $iT = TimerInit() $iCount = _FileCountLines("test.txt") ; Anzahl aller Zeilen in Datei If StringLen(FileReadLine("test.txt", -1)) <> 192 Then $iCount -= 1 ; Falls letzte Zeile <> 192 Zeichen, dann abziehen $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%12.4f ms\t% 6d\n", "_FileCountLines", $iT, $iCount)) ; variant with _FileReadToArray $iT = TimerInit() Local $aFile, $iCount = 0 _FileReadToArray("test.txt", $aFile) For $j = 1 To $aFile[0] If StringLen($aFile[$j]) = 192 Then $iCount += 1 Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%12.4f ms\t% 6d\n", "_FileReadToArray", $iT, $iCount)) ; variant with FileReadLine $iT = TimerInit() Local $hFile = FileOpen("test.txt", 0), $iCount = 0, $sLine While 1 $sLine = FileReadLine($hFile) If @error = -1 Then ExitLoop If StringLen($sLine) = 192 Then $iCount += 1 WEnd FileClose($hFile) $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%12.4f ms\t% 6d\n", "FileReadLine", $iT, $iCount)) ; variant with FileReadToArray $iT = TimerInit() Local $iCount = 0 Local $aFile = FileReadToArray("test.txt") For $j = 0 To @extended - 1 If StringLen($aFile[$j]) = 192 Then $iCount += 1 Next $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%12.4f ms\t% 6d\n", "FileReadToArray", $iT, $iCount)) ; variant with StringRegExpReplace $iT = TimerInit() StringRegExpReplace(FileRead("test.txt"), '(?m)^.{192}$', '') Local $iCount = @extended $iT = TimerDiff($iT) ConsoleWrite(StringFormat("% 20s:\t%12.4f ms\t% 6d\n\n", "StringRegExpReplace", $iT, $iCount)) ##EndRegion
-
Die letzte Zeile ist mir für mein weiteres Vorhaben nicht relevant. Also genau anders wie ihr gedacht habt.
Wobei ich aus den Beiträgen einiges dennoch gelernt habe, sage ich DANKE !!!
-
Moin,
wenn jede Zeile bis auf die letzte immer 192 Zeichen lang ist, ist jede dieser Zeilen unter Windows in der per FileRead() beschickten Variablen 194 Zeichen lang (CRLF). Dann sollte Folgendes funktionieren:
-
Moin,
wenn jede Zeile bis auf die letzte immer 192 Zeichen lang ist, ist jede dieser Zeilen unter Windows in der per FileRead() beschickten Variablen 194 Zeichen lang (CRLF). Dann sollte Folgendes funktionieren:
Das bitte ich einmal zu erklären.
Bis jetzt dachte ich immer 1 Byte = 1 Buchstabe / Zahl / ....
alle Zeilen haben 192, außer ggf. die Letzte Zeile, die aber auch 192 lange sein kann.
Aber wie oben geschrieben, es ist alles geklärt und funktioniert. -
Hallo,
in einer Textdatei gibt es Zeilenumbrüche. Die bestehen unter Windows normalerweise aus 2 Zeichen CR und LF (@CRLF). So sind die führenden Zeilen mit 192 Zeichen tatsächlich 194 Zeichen lang.
-
Ja, okay.
Aber der String selber ist ja 192 Zeichen lang und das meine ich habe ich doch in meiner Lösung richtig gemacht.
Wenn ich die Zeichen händisch zähle sind es auch 192 sichtbare Zeichen. @CRLF sind unsichtbar und ich habe die ja auch händisch nicht mitgezählt.
Weiß jetzt nicht, was ich denken soll. Bin total verwirrt. War das eine allgemeine Information von Dir odr ein HInweis, das der o. g. Skript doch nicht fehlerfrei ist?
-
Weiß jetzt nicht, was ich denken soll. Bin total verwirrt.
Da Du die Zeilen mit FileReadLine einliest, gilt (aus der Hilfe) :
Bemerkungen
Gibt eine Textzeile zurück. Die am Zeilenende eingelesenen Zeilenumbrüche (@CR oder @LF) werden automatisch entfernt.
-
Moin Alina,
tut mir leid, wenn ich Dich irritiert habe. Mit meinem Beitrag wollte ich nicht sagen, dass die bereits vorgestellten Lösungen falsch sind. Ich wollte nur für diesen speziellen Fall, wenn alle Zeilen bis auf die letzte gleich lang sind, noch eine Alternative aufzeigen, die die Datei nicht zeilenweise bearbeitet. Die StringRegExReplace() Variante von AspirinJunkie aus Beitrag #10 verarbeitet den Dateiinhalt auch als Block.
-
Okay, dann weiß ich bescheid. DANKE !!!
-