Seite 1 von 2

Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 06:12
von tim
Hallo,

mir fällt leider keine sinnvolle Lösung für folgendes Problem ein:
Ich möchte die erste Zeile einer Textdatei auslesen, dann die
erste Zeile löschen und den Rest "nach oben rutschen lassen".

Textdatei vorher:

Code: Alles auswählen

aaaaa
bbbbb
ccccc
ddddd
eeeee
.....

Textdatei nachher:

Code: Alles auswählen

bbbbb
ccccc
ddddd
eeeee
.....

Auf diese Weise möchte ich die Textdatei gern, Schritt für Schritt, abarbeiten.


Würde mich sehr über eine kleine Hilfe freuen!


Gruß
Tim

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 08:38
von Drago
Guten Morgen die Dame.. :D

Ich kenne mich mit solchen Dingen nicht besonders aus, ber mir ist dazu eine Idee gekommen.
In der Hilfe steht für die ASCII Zeichen..
13 Wagenrücklauf. Das Zeichen, welches den Kopf einer Schreibmaschine oder eines Druckers auffordert, sich zurück zum Anfang einer Zeile zu bewegen. Normalerweise verwendet als das - oder Teil des - 'End of Line' (Ende der Zeile) Zeichens.
Teste beim Einlesen einfach auf diesen ASCII - Wert, dann müsste es doch klappen..

LG Drago

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 08:49
von Drago
Syntax

Text$ = ReadString(#Datei [, Flags])
Beschreibung

Liest einen String aus einer Datei bis ein 'End Of Line' (EOF - in Deutsch: "Ende der Zeile") Zeichen gefunden wird (Unix- und DOS-Dateiformate werden unterstützt).
Oder so etwas benutzen, je nachdem, wie du deinen Text ausliest..
Ohne Code, schwer....

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 10:29
von Falko
Versuchs mal hiermit, indem eine Kopie von deiner Textdatei gemacht wird,
und diese dann Zeile für Zeile ohne der ersten in deine Textdatei neu
geschrieben wird.

Code: Alles auswählen

Procedure.s EraseFirstText(MyDat.s)
  Protected VirtDat.s="MyText.$$$",ErsteZeile.s
  If FileSize(MyDat)=>0
    If CopyFile(MyDat,VirtDat)
       OpenFile(0,VirtDat)
       CreateFile(1,MyDat)
       ReadFile(0,VirtDat)
       ErsteZeile=ReadString(0)
       FileSeek(0,Len(ErsteZeile))
       WriteString(1,ReadString(0))
       While Eof(0)=0
         WriteStringN(1,ReadString(0,#PB_Ascii))
       Wend
       CloseFile(1)
       CloseFile(0)
       DeleteFile(VirtDat)
     Else
       MessageRequester("Achtung!","Die Datei konnte nicht kopiert werden")
     EndIf
  Else
    MessageRequester("Achtung","Ist die Datei vorhanden und nicht leer?")
   EndIf
   ProcedureReturn ErsteZeile
EndProcedure



MessageRequester("1.Zeile ausgeben",EraseFirstText("MyDat.txt"))
Gruß,
Falko

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 10:59
von ts-soft
Hier eine etwas einfachere und schnellere Lösung:

Code: Alles auswählen

EnableExplicit

Define FF, Format, File.s = "d:\wichtig.txt" ; <- hier anpassen
Define length, *mem, pos

FF = OpenFile(#PB_Any, File)
If FF
  Format = ReadStringFormat(FF)                         ; Stringformat sichern.
  length = Lof(FF)                                      ; länge ermitteln.
  *mem = AllocateMemory(length)                         ; Speicher reservieren.
  If *mem
    ReadData(FF, *mem, length)                          ; Daten in den Speicher lesen.
    pos = FindString(PeekS(*mem, -1, Format), #LF$)     ; erstes Zeilenende Zeichen suchen.
    If pos
      FileSeek(FF, 0)                                   ; wenn gefunden, zurück an den Anfang.
      WriteStringFormat(FF, Format)                     ; BOM schreiben.
      WriteData(FF, *mem + pos, length - pos)           ; Daten ab gefundener pos schreiben.
      TruncateFile(FF)                                  ; Rest vom Orginal abschneiden.
    EndIf
    FreeMemory(*mem)                                    ; Speicher freigeben.
  EndIf
  
  ;ab hier neue Zeilen Schreiben.
  ;WriteStringN(FF, "bla", Format)
  CloseFile(FF)
EndIf
Gruß
Thomas

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 11:25
von Andreas21
So würde ich es machen.

Code: Alles auswählen

EnableExplicit

Define FF, Format, File.s = "wichtig.txt" ; <- hier anpassen
Define length, *mem, tmp.s

FF = OpenFile(#PB_Any, File)
If FF
  Format = ReadStringFormat(FF)                       ; Stringformat sichern.
  length = Lof(FF)                                    ; länge ermitteln.
  tmp = ReadString(FF, Format)                        ; Die erste Zeile einlesen
  length = length - Loc(FF)                           ; Die Aktuelle Position von der gesamtlänge abziehen.
  *mem = AllocateMemory(length)                       ; Speicher reservieren.
  If *mem
    ReadData(FF, *mem, length)                        ; Daten in den Speicher lesen.
    FileSeek(FF, 0)                                   ; wenn gefunden, zurück an den Anfang.
    WriteStringFormat(FF, Format)                     ; BOM schreiben.
    WriteData(FF, *mem, length)                       ; Daten ab gefundener pos schreiben.
    TruncateFile(FF)                                  ; Rest vom Orginal abschneiden.
    FreeMemory(*mem)                                  ; Speicher freigeben.
  EndIf
 
  ;ab hier neue Zeilen Schreiben.
  ;WriteStringN(FF, "bla", Format)
  CloseFile(FF)
EndIf

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 11:37
von ts-soft
@Andreas21

Warum liest Du die erste Zeile mit dem langsamen ReadString aus?
#LF$ ist in jeder Textdatei als Zeilenende vorhanden, egal ob
Windows oder Linux. Wenn #CRLF$ ändert nichts an der Zuverlässigkeit
meiner Routine, lediglich bei älteren Mac-Systemen könnte es versagen,
da nur #CR$ vorhanden.

Ansonsten ist es auch mehr Geschmackssache :wink:

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 12:10
von Falko
Dann nehmen wir auch
nochmal LinkedList() hinzu :wink:
[Edit] Auswahl der jeweilig zu löschenden Zeile ist hiermit möglich.
Auch im nachfolgenden Beitrag von TS-Soft beschriebenen ASCII-Formaten,
habe ich das auch im Code hinzugefügt. Also UTF-8 ist möglich :wink:
[/Edit]

Code: Alles auswählen

EnableExplicit
Procedure.s EraseTextLines(MyDat.s,line.l)
  Protected Result.s,Format
  NewList TLine.s()
  If FileSize(MyDat)=>0
    ;Einlesen der kompletten Textdatei in den Speicher
    OpenFile(0,MyDat)
    Format=ReadStringFormat(0)
    While Eof(0)=0 
      AddElement(TLine())
      TLine()=ReadString(0,Format)
    Wend
    CloseFile(0)
    ;Schreiben aus dem geänderten Speicherinhalt wieder in die Datei
    CreateFile(0,MyDat)
    SelectElement(TLine(),line-1)
    Result=TLine()
    DeleteElement(TLine())
    ResetList(TLine())
    While NextElement(TLine()) 
      WriteStringN(0,TLine(),Format)
    Wend
    CloseFile(0)
   Else
     MessageRequester("Achtung","Ist die Datei vorhanden und nicht leer?")
   EndIf
   ProcedureReturn Result
EndProcedure

MessageRequester("Gelöschte Zeile",EraseTextLines("MyText.txt",1))
Gruß
Falko

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 12:20
von ts-soft
@Falko

Naja, Textformat wird nicht berücksichtigt (funktioniert nur mit ASCII-Texten, die es kaum noch gibt,
heutzutage sind die meisten Textdateien in UTF-8 codiert), und auch langsamer, was bei kleineren
Dateien natürlich keine Rolle spielt. Vorteile kann ich keine erkennen, ganz im Gegenteil :wink:

// edit
Hab meinen Code nochmals optimiert. Hab es in eine Procedure gepackt und jetzt wird auch
berücksichtigt, wenn die letzte Zeile kein EOL (EndOfLine) enthält.

Code: Alles auswählen

EnableExplicit

Procedure RemoveFirstLine(File, EOL.s = #LF$)
  Protected Format, length.q, *mem, pos.q
 
  If IsFile(File)
    FileSeek(File, 0)
    Format = ReadStringFormat(File)
    length = Lof(File)
    If length
      *mem = AllocateMemory(length)
      ReadData(File, *mem, length)                          ; Daten in den Speicher lesen.
      pos = FindString(PeekS(*mem, -1, Format), EOL)      ; erstes Zeilenende Zeichen suchen.
      If pos
        WriteStringFormat(File, Format)                     ; BOM schreiben.
        WriteData(File, *mem + pos, length - pos)           ; Daten ab gefundener pos schreiben.
        TruncateFile(File)                                  ; Rest vom Orginal abschneiden.
        If PeekS(*mem + length - Len(EOL), Len(EOL), Format) <> EOL
          WriteStringN(File, "", Format)
        EndIf
      EndIf
      FreeMemory(*mem) 
    EndIf  
  EndIf
  ProcedureReturn Format
EndProcedure

Define Format, FF = OpenFile(#PB_Any, "wichtig.txt")
If FF
  Format = RemoveFirstLine(FF)
  WriteStringN(FF, "Ich bin die neue letzte Zeile", Format)
  ; ...
  CloseFile(FF)
EndIf
// edit
noch mal fehler beseitigt bei leerer Datei.

Re: Textdatei auslesen und erste Zeile löschen?

Verfasst: 23.03.2012 12:47
von CSHW89
ts-soft hat geschrieben:@Andreas21

Warum liest Du die erste Zeile mit dem langsamen ReadString aus?
#LF$ ist in jeder Textdatei als Zeilenende vorhanden, egal ob
Windows oder Linux. Wenn #CRLF$ ändert nichts an der Zuverlässigkeit
meiner Routine, lediglich bei älteren Mac-Systemen könnte es versagen,
da nur #CR$ vorhanden.

Ansonsten ist es auch mehr Geschmackssache :wink:
Naja, selbst wenn eine Datei richtig groß ist, spielt, glaube ich, EIN Aufruf von ReadString keine Rolle, zumal es dann auch sicherer ist, wie du schon sagt, falls das Zeilenende nur #CR$ ist.

@Andreas21, @ts-soft:
Ach ja, falls die Datei leer ist, gibts bei euch beiden ein Fehler, und wenn die Datei nur aus einer Zeile besteht (ohne Zeilenumbruch), gibts bei Andreas21 auch ein Fehler und bei ts-soft macht er nix, löscht also nicht die eine Zeile. Also wäre meine Lösung:

Code: Alles auswählen

EnableExplicit

Define FF, Format, File.s = "wichtig.txt" ; <- hier anpassen
Define length, *mem, tmp.s

FF = OpenFile(#PB_Any, File)
If FF
  Format = ReadStringFormat(FF)                       ; Stringformat sichern.
  length = Lof(FF)                                    ; länge ermitteln.
  tmp = ReadString(FF, Format)                        ; Die erste Zeile einlesen
  length = length - Loc(FF)                           ; Die Aktuelle Position von der gesamtlänge abziehen.
  If length
    *mem = AllocateMemory(length)                       ; Speicher reservieren.
    If *mem
      ReadData(FF, *mem, length)                        ; Daten in den Speicher lesen.
      FileSeek(FF, 0)                                   ; wenn gefunden, zurück an den Anfang.
      WriteStringFormat(FF, Format)                     ; BOM schreiben.
      WriteData(FF, *mem, length)                       ; Daten ab gefundener pos schreiben.
      TruncateFile(FF)                                  ; Rest vom Orginal abschneiden.
      FreeMemory(*mem)                                  ; Speicher freigeben.
    EndIf
  Else
    FileSeek(FF, 0)
    WriteStringFormat(FF, Format)
    TruncateFile(FF)
  EndIf
 
  ;ab hier neue Zeilen Schreiben.
  ;WriteStringN(FF, "bla", Format)
  CloseFile(FF)
EndIf
lg Kevin

Edit: edit von ts-soft zu spät gesehen :mrgreen: