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.