Seite 1 von 1
File Rückwärts lesen?
Verfasst: Freitag 2. März 2007, 11:03
von THE_ONE
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
Verfasst: Freitag 2. März 2007, 11:23
von rayo
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
Verfasst: Freitag 2. März 2007, 11:43
von THE_ONE
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
Verfasst: Freitag 2. März 2007, 11:53
von rayo
Hi
Zuerst musst du den Dateizeiger um x-Bytes zurücksetzen und dann wieder soviel einlesen.
Gruss
Verfasst: Freitag 2. März 2007, 12:41
von Y0Gi
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.
Verfasst: Freitag 2. März 2007, 13:13
von Masaru
Hmm ... musst Du denn alle Zeilen invertiert einlesen, oder reichen vielleicht auch die letzten X?
Verfasst: Freitag 2. März 2007, 14:03
von THE_ONE
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
Verfasst: Freitag 2. März 2007, 14:57
von THE_ONE
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
Verfasst: Freitag 2. März 2007, 16:56
von Y0Gi
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
Verfasst: Donnerstag 21. August 2008, 11:20
von Rene_F
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?
Verfasst: Donnerstag 21. August 2008, 11:43
von 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()
Verfasst: Donnerstag 21. August 2008, 14:44
von CM
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() -
Verfasst: Donnerstag 21. August 2008, 15:58
von Leonidas
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.
Verfasst: Donnerstag 21. August 2008, 19:56
von BlackJack
@CM: Argh, ja da wollte ich natürlich über `lines` iterieren.
Verfasst: Freitag 22. August 2008, 09:35
von CM
Leonidas hat geschrieben:Schon mal das Ausgangsposting angesehen?
Autsch - tja, da hatten wohl gleich zwei gestern eine bes. Phase hoher Konzentration
.
Verfasst: Samstag 23. August 2008, 15:06
von dennda
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.