File Rückwärts lesen?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
THE_ONE
User
Beiträge: 4
Registriert: Freitag 2. März 2007, 10:47

Hallo!

Bin neu bei Python und hab auch schon mein erstes Programm laufen. Nun steh ich aber an einem simplen Problem an.

Ich habe eine Funktion die mir jede Zeile eines Files abarbeitet! um die Zeile einzulesen verwenden ich:

Code: Alles auswählen

def exec_step():
  cmd = cmds.readline()
.
.
cmds = open(cmd_file, 'r')
Jetzt bräuchte ich aber noch die Möglichkeit in die andere Richtung zu lesen, also rückwärts (einen step zurück, die vorige Zeile eben)-> gibt es dafür eine Funktion??
Was ich nicht will ist das ganze mit readlines lösen. Denn ich will nicht das ganze File, das schon mal 80MB haben kann, in den Speicher laden.[/b]
MFG THE_ONE
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Du könntest schrittweise z.B. die 1000 letzten Zeichen einlesen und darin dann einen Zeilenumbruch suchen.

Etwas anderes kenn ich nicht um rückwärts einlesen.

Gruss
THE_ONE
User
Beiträge: 4
Registriert: Freitag 2. März 2007, 10:47

Danke für die Antwort!
Das ist eigentlich eine gute Idee da die Zeile bei mir eh nur einen gewisse maximale Länge haben. Nur leider hab i grade überhaupt keinen Plan wie man Zeichen Rückwärts liest. Gibt es eine Funktion die ich direkt auf cmds bzw cmd anwenden könnte?
MFG
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Zuerst musst du den Dateizeiger um x-Bytes zurücksetzen und dann wieder soviel einlesen.

Code: Alles auswählen

cmds.seek(-1000, 1)
cmds.read(1000)
Gruss
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Manchmal reicht es, wenn man durch das File iteriert (`for line in filehandle:`, dann wird ja nicht alles in den Speicher geladen) und die aktuelle Zeile zwischenspeichert, um im nächsten Schritt darauf zugreifen zu können. Wenn du aber mehrere Zeilen zurück lesen können willst, wird das schon problematischer.
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Hmm ... musst Du denn alle Zeilen invertiert einlesen, oder reichen vielleicht auch die letzten X?
THE_ONE
User
Beiträge: 4
Registriert: Freitag 2. März 2007, 10:47

mir würde es reichen immer nur eine Zeile rückwärts zu gehen.
Vielleicht beschreibe ich das ganze mal genauer:
in dem zu lesenden file steht in jeder Zeile ein Befehl (variabler Länge) den ich per Python auswerte. Auszug aus dem file:

Code: Alles auswählen

 2007 3 2 45477.750997333 new 1 1
 2007 3 2 45477.751128356 smell 1 1
 2007 3 2 45477.763601170 rotate 1 1
 2007 3 2 45477.776096054 rotate 1 1
 2007 3 2 45477.788772526 smell 1 1
 2007 3 2 45477.788820576 move 1 1 2 1
.
.


Jedesmal wenn ich auf den Button Step drücke wird um eine Zeile weitergesprungen und diese evaluiert.
Jetzt habe ich einen Button Prev und wenn ich auf diesen drücke würde ich gerne eine Zeile zurückgehen und diese auswerten.

hab dazu folgendes probiert:

Code: Alles auswählen

  while cmd != '\n': 
    
	cmds.seek(-2,1)
	cmd = cmds.read(1)
  cmds.seek(-2,1)  #wenn ich Ende der zeile gefunden hab noch eins zurück
  cmd = cmds.readline()
->funktioniert aber leider nicht.

MFG THE_ONE
THE_ONE
User
Beiträge: 4
Registriert: Freitag 2. März 2007, 10:47

So hab jetzt die Lösung:

Code: Alles auswählen

rowlength = 0

def exec_step():
  global c,col,rowlength
  cmd = cmds.readline()
  rowlength = len(cmd)
.
.

def exec_prev():
  global c,col,rowlength
  cmds.seek(-(rowlength+4),1)
  cmd = 'd'
  while cmd != '\n': 
    
	cmds.seek(-2,1)
	cmd = cmds.read(1)
	#print cmd
  cmd = cmds.readline()	 
  rowlength= len(cmd)
  #print cmd
.
.
Das einzige was nicht funktioniert ist das ich die erste zeile lesen kann (d.h. wenn man bei der zweiten Zeile steht und man exec_prev aufruft bekommt man einen Fehler, aber so weit will ich eigentlich eh nie zurück ), aber sonst funktionierts.
MFG THE_ONE
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Was spricht denn gegen dieses hier?

Code: Alles auswählen

FILENAME = 'test.dat'

line_cache = None
for line in open(FILENAME, 'rb'):
    line_cache = line
    # Prüfen, ob diese Zeile leer ist.
    if not line.strip():
        print 'Die vorherige Zeile war:'
        print '    ' + line_cache
Rene_F
User
Beiträge: 1
Registriert: Donnerstag 21. August 2008, 11:10

Y0Gi hat geschrieben:Was spricht denn gegen dieses hier?

Code: Alles auswählen

FILENAME = 'test.dat'

line_cache = None
for line in open(FILENAME, 'rb'):
    line_cache = line
    # Prüfen, ob diese Zeile leer ist.
    if not line.strip():
        print 'Die vorherige Zeile war:'
        print '    ' + line_cache

Hallöle!

Irgendwie macht das Skript bei mir nicht so viel, alles was ich als Ausgabe bekomme ist:

Code: Alles auswählen

Die vorherige Zeile war:
    

Die vorherige Zeile war:
    

Die vorherige Zeile war:
    

Die vorherige Zeile war:
    

Die vorherige Zeile war:
    

Die vorherige Zeile war:
    

Die vorherige Zeile war:
    

Die vorherige Zeile war:
Es sind sowohl leere Zeilen in der Datei, als auch etwas Text.
Und kann es sein, dass das Skript die Datei nicht rückwärts ausliest?
BlackJack

Ja, das liest die Datei nicht rückwärts aus, sondern merkt sich immer die vorherige Zeile. Die Bedingung beim ``if`` ist aber falsch. So funktionierts:

Code: Alles auswählen

def main():
    FILENAME = 'test.txt'
    
    line_cache = None
    lines = open(FILENAME)
    for line in open(FILENAME, 'rb'):
        line_cache = line
        if line_cache is not None:
            print 'Die vorherige Zeile war:'
            print '    ' + line_cache
    lines.close()
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

also die Lösung funktioniert zwar, aber 'lines' zu öffnen und dann schliessen ohne drauf zuzugreifen und direkt über 'open(FILENAME, 'rb')' zu loopen sieht schon iritierend aus.

Wenn die Datei nicht allzu groß ist geht auch:

Code: Alles auswählen

infile = open('text.txt')
lines = infile.readlines()
infile.close()

for revert_line in lines[::-1]:
   print revert_line
Was ggf. auch aufzuhübschen ist.

Gruß,
Christian

edit: readlines(infile) zu infile.readlines() - :oops:
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

CM hat geschrieben:Wenn die Datei nicht allzu groß ist
Schon mal das Ausgangsposting angesehen? ;) Die Datei ist mit 80MB nicht zu groß, aber der OP will es dennoch nicht in den Speicher laden.

Letztendlich wäre es wohl am simpelsten ``read_backwards`` zu implementieren, was n Bytes von hinten liest (und vorher natürlich ``seek()``t) und dann ``readlines_backwards`` zu implementieren, was jeweils ``read_backwards(1)`` aufruft, guckt ob das ein ``\n`` ist und ggf. eine neue Zeile yielded. Als Optimierung kann man einen Generator bauen, der größere Brocken via ``read_backwards()`` einliest und cached, Newlines sucht und dann jeweils Zeilen sucht, die ge``yield``ed werden. Wenn keine Newlines mehr vorhanden sind, den Cache einfach mit einem neuen Brocken auffüllen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@CM: Argh, ja da wollte ich natürlich über `lines` iterieren. :oops:
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Leonidas hat geschrieben:Schon mal das Ausgangsposting angesehen?
Autsch - tja, da hatten wohl gleich zwei gestern eine bes. Phase hoher Konzentration ;-).
Benutzeravatar
dennda
User
Beiträge: 17
Registriert: Montag 19. November 2007, 22:07

Hi. Ich habe jetzt hier nicht alles gelesen sondern nur kurz das Startposting überflogen. Genauer gesagt habe ich mir nicht mal sonderlich viele Gedanken gemacht weil ich grade in Eile bin. Ich dachte nur ich lasse das hier mal da, vielleicht ist es ja hilfreich:
seek(...)
seek(offset[, whence]) -> None. Move to new file position.

Argument offset is a byte count. Optional argument whence defaults to
0 (offset from start of file, offset should be >= 0); other values are 1
(move relative to current position, positive or negative), and 2 (move
relative to end of file,
usually negative, although many platforms allow
seeking beyond the end of a file). If the file is opened in text mode,
only offsets returned by tell() are legal. Use of other offsets causes
undefined behavior.
Note that not all file objects are seekable.
Antworten