Seite 1 von 1
ReadFile/String vom Ende der Datei?
Verfasst: 25.09.2017 20:39
von Fox
Hallo PureBoard!
Ich hadere nun schon eine ganze Zeit bei einem Problem, welches sich aus meinem Vorhaben ergibt.
Eine Textdatei soll an 2 Stellen um mehrere Zeilen Inhalt ergänzt werden. Die erste Ergänzung soll dabei vor dem String"Mode" erfolgen, jedoch ausschließlich davor und einmalig. Am Ende der Datei soll eine Ergänzung um 2 Strings bei dem String "M5" erfolgen, auch hier einmalig. Da innerhalb der Datei sowohl der String "Mode" als auch der String "M5" mehrmals vorkommen, die Datei aber Zeile für Zeile ausgelesen und mittels ReplaceString dabei jeder String mit dem entsprechendem Inhalt ersetzt wird, ergibt sich das Problem. Daher die Frage, gibt es eine Möglichkeit die Datei und deren Strings vom Ende der Datei aus zu lesen? Oder eine eleganter Lösung?
Re: ReadFile/String vom Ende der Datei?
Verfasst: 26.09.2017 07:28
von ProgOldie
Die Art der Lösung hängt davon ab, wie groß die Textdatei ist.
a) Bei kleinen Dateien: Alle Zeilen in den Speicher lesen, bearbeiten und dann komplett neu in die Datei zurückschreiben.
b) Bei größeren Dateien: Zunächst eine neue (temp-Datei) anlegen. Dann die ursprüngliche Datei durchlesen und dabei immer einige Zeilen ins RAM. Dann diese bearbeiten und anschließend an die temp-Datei anhängen. Zum Schluss die temp-Datei abspeichern. Das funktioniert bei jeder Dateigröße.
Das einzige Problem bei b) könnte ein ggf. zeitkritisches sein, weil ja die ganze Datei zeilenweise gelesen werden muss.
Und was das Lesen "vom Ende her" betrifft, da gibt es FILESEEK(), das besonders praktisch ist, wenn man die Länge der (Text-)Zeilen kennt. Beispiel aus der Hilfe:
Code: Alles auswählen
file$ = OpenFileRequester("Select a file","","Text (.txt)|*.txt|All files (*.*)|*.*",0)
If file$
If ReadFile(0, file$)
length = Lof(0) ; read length of file
FileSeek(0, length - 10) ; set the file pointer 10 chars from end of file
Debug "Position: " + Str(Loc(0)) ; show actual file pointer position
*MemoryID = AllocateMemory(10) ; allocate the needed memory for 10 bytes
If *MemoryID
bytes = ReadData(0, *MemoryID, 10) ; read this last 10 chars in the file
Debug PeekS(*MemoryID)
EndIf
CloseFile(0)
EndIf
EndIf
Re: ReadFile/String vom Ende der Datei?
Verfasst: 26.09.2017 14:55
von Fox
Danke für die schnelle Antwort. Die Textdateien sind im Schnitt 7-15MB groß, daher dauert es logischerweise etwas bis die Datei eingelesen ist.
Die beiden Strings die am Ende der Datei stehen sollen, werden immer in die vorletzte Zeile der Datei geschrieben.
Ist folgende Überlegung sinnvoll?
Schleife von 0-49, d.h. Datei von Zeile 0 bis Zeile 50 einlesen und mittels WriteStringN(), wenn ReadString(0) = “Mode”, die einzufügenden Strings in die Datei schreiben.
Anschließend Zeile 51 bis Ende der Datei lesen und in die Datei schreiben.
Nun zwei Zeilen über dem Eof die anderen beiden Strings einfügen und die Datei schließen.
Würde das funktionieren oder bin ich komplett auf dem Holzweg?
Die Zeilenlängen in der Quelldatei sind übrigens variabel und nicht bekannt.
Re: ReadFile/String vom Ende der Datei?
Verfasst: 26.09.2017 16:35
von ts-soft
Erst mal die Textdatei richtig schnell einlesen, sonst wird das nichts
Crossplattform wäre dann mit ReadData(), natürlich die ganze Datei einlesen, suchen tun wir wenn die Datei eingelesen wurde!
Oder für Windows in ein Control:
Code: Alles auswählen
Procedure StreamFileIn_Callback(hFile, pbBuff, cb, pcb)
ProcedureReturn ReadFile_(hFile, pbBuff, cb, pcb, 0)!1
EndProcedure
Procedure Editor_Load(Gadget, File.s)
Protected FileID = ReadFile(#PB_Any, File)
Protected StreamData.EDITSTREAM
If FileID
StreamData\dwCookie = FileID(FileID)
StreamData\dwError = #Null
StreamData\pfnCallback = @StreamFileIn_Callback()
If UCase(GetExtensionPart(File)) = "RTF"
SendMessage_(GadgetID(Gadget), #EM_STREAMIN, #SF_RTF, @StreamData)
Else
SendMessage_(GadgetID(Gadget), #EM_STREAMIN, #SF_TEXT, @StreamData)
EndIf
CloseFile(FileID)
EndIf
EndProcedure
If OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "Editor-Test", #PB_Window_SystemMenu | #PB_Window_Invisible)
EditorGadget(0, 5, 5, WindowWidth(0) - 10, WindowHeight(0) - 10)
Editor_Load(0, #PB_Compiler_Home + "SDK\Readme.txt")
While WindowEvent() : Wend
HideWindow(0, #False)
While WaitWindowEvent() <> #PB_Event_CloseWindow : Wend
EndIf
Das geht natürlich auch "Superschnell", vor allem im Vergleich mit Zeilenweise einlesen.
Jetzt z.B. den Suchen... Dialog im EditorGadget starten oder nach LF$ im Speicher von hinten suchen um Zeilen zu bilden.
Auf jeden Fall haste erstmal einen Anfang.
Gruß
Thomas
Re: ReadFile/String vom Ende der Datei?
Verfasst: 26.09.2017 22:34
von Fox
Vielen Dank Thomas, hat mir super geholfen und ich bin zum gewünschten Ergebnis gelangt.