Finden, lesen und schreiben von Informationen

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
Blackgarfield
User
Beiträge: 5
Registriert: Mittwoch 30. August 2006, 16:11
Wohnort: Cottbus

Hallo,

will Dateien auslesen, die komplett gleich aussehen (Anzahl der Zeilen Wörter etc.). Nur die Werte ändern sich von Datei zu Datei und ich benötige Diverse Werte aus solchen Dateien.
Bisher lasse ich eine Schleife durchlaufen, die die Dateien öffnet (sie unterscheiden sich im Namen auch nur durch Zahlen) dann an gewisse stellen springt und die Werte auslies (siehe unten):

Code: Alles auswählen

f=file(filename_PS_ctr+i,'r')
	
f.seek(1143)
p_x_in = f.read(14)	
print p_x_in
f.seek(1192)
p_x_ex = f.read(14)	
print p_x_ex	

f.seek(2181)
blend_point_ps_m = f.read(11)
f.seek(2194)
blend_point_ps_theta = f.read(11)
print blend_point_ps_m
print blend_point_ps_theta

f.seek(2240)
blend_point_ss_m = f.read(11)
f.seek(2253)
blend_point_ss_theta = f.read(11)
print blend_point_ss_m
print blend_point_ss_theta
die print-befehle dienen mir z.Z. nur als Kontrolle.
Ich finde meine Art und Weise aber eher zu den Stellen zu gelangen ein bisschen primitiv. Nun die Frage:

Kann ich nicht zum Beispiel die ersten 30 Zeilen als Zeilen einlesen, zu der bestimmten Zeile springen und alles nach einem bestimmten Zeichen oder Wort einlesen? Mit dem Befehl
"strInp=datei.readlines()"
kann ich zwar Zeilenweise einlesen, aber ich weis nicht, wie man nur bis zu einer bestimmten Zeile einliest, wie man innerhalb eine Zeile ein Wort/Zeichen sucht und den nachfolgenden Inhalt einliest?

Habt ihr da eine Idee??

Vielen Dank

Edit (Leonidas): Code in Python-Tags gesetzt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Blackgarfield hat geschrieben:Kann ich nicht zum Beispiel die ersten 30 Zeilen als Zeilen einlesen, zu der bestimmten Zeile springen und alles nach einem bestimmten Zeichen oder Wort einlesen? Mit dem Befehl
"strInp=datei.readlines()"
kann ich zwar Zeilenweise einlesen, aber ich weis nicht, wie man nur bis zu einer bestimmten Zeile einliest, wie man innerhalb eine Zeile ein Wort/Zeichen sucht und den nachfolgenden Inhalt einliest?
Ich habe mal deinen Code in Python-Tags gesetzt, mach das aber bitte das nächste mal selbst.

Nun zu deiner Frage: die ersten 30 Bytes bekommtst du mit f.read(30) aber du kannst auch die ganze Datei mit regulären Ausdrücken durchsuchen lassen, das ist sicherlich universeller.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Blackgarfield hat geschrieben:

Code: Alles auswählen

f=file(filename_PS_ctr+i,'r')
	
f.seek(1143)
p_x_in = f.read(14)	
print p_x_in
f.seek(1192)
p_x_ex = f.read(14)	
print p_x_ex	

f.seek(2181)
blend_point_ps_m = f.read(11)
f.seek(2194)
blend_point_ps_theta = f.read(11)
print blend_point_ps_m
print blend_point_ps_theta

f.seek(2240)
blend_point_ss_m = f.read(11)
f.seek(2253)
blend_point_ss_theta = f.read(11)
print blend_point_ss_m
print blend_point_ss_theta
die print-befehle dienen mir z.Z. nur als Kontrolle.
Ich finde meine Art und Weise aber eher zu den Stellen zu gelangen ein bisschen primitiv. Nun die Frage:
Warum primitiv? Wenn die Werte immer an den gleichen Stellen stehen, dann ist das doch die direkteste Methode. Du könntest das lesen in eine Funktion auslagern, die eine Folge von Tupeln mit Offset und Länge bekommt, damit diese Werte alle an einer Stelle im Programm stehen und nicht so über die Funktion verteilt sind und Du ein wenig Schreibarbeit sparen kannst:

Code: Alles auswählen

def read(fileobj, locations):
    result = list()
    for offset, length in locations:
        fileobj.seek(offset)
        result.append(fileobj.read(length))
    return result


def test():
    f=file(filename_PS_ctr+i,'r') 
    values = read(f, ((1143, 14), (1192, 14), (2181, 11), (2194, 11),
                      (2240, 11), (2253, 11)))
    f.close()
    print values
Anstelle von `values` kannst Du natürlich ein Tupel mit den einzelnen Namen schreiben, auf die das Ergebnis dann verteilt wird.
Kann ich nicht zum Beispiel die ersten 30 Zeilen als Zeilen einlesen, zu der bestimmten Zeile springen und alles nach einem bestimmten Zeichen oder Wort einlesen? Mit dem Befehl
"strInp=datei.readlines()"
kann ich zwar Zeilenweise einlesen, aber ich weis nicht, wie man nur bis zu einer bestimmten Zeile einliest, wie man innerhalb eine Zeile ein Wort/Zeichen sucht und den nachfolgenden Inhalt einliest?
Wie gross sind die Dateien denn? Lohnt sich das begrenzen auf Beispielsweise 30 Zeilen? Falls ja, dann ist das einfachste wohl `itertools.islice()`:

Code: Alles auswählen

from itertools import islice


def main():
    in_file = open('test.py', 'r')
    lines = list(islice(lines, 30))
    in_file.close()
Das liest die ersten 30 Zeilen in eine Liste ein.

Die Position einer Zeichenkette in einer anderen, kann man mit der `index()`-Methode herausfinden:

Code: Alles auswählen

In [54]: a = 'answer=42;'

In [55]: a.index('=')
Out[55]: 6

In [56]: a[7:9]
Out[56]: '42'
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Blackgarfield hat geschrieben:will Dateien auslesen, die komplett gleich aussehen (Anzahl der Zeilen Wörter etc.). Nur die Werte ändern sich von Datei zu Datei und ich benötige Diverse Werte aus solchen Dateien.
Nichts gegen deine Absicht, Python zu verwenden, aber genau für solche Einsatzgebiete sind sed und awk geschaffen worden.
Blackgarfield
User
Beiträge: 5
Registriert: Mittwoch 30. August 2006, 16:11
Wohnort: Cottbus

Hi Leute danke für eure Hilfe. Ich habe mir den Tip von Blackjack zu Herzen genommen und es so gelöst:

Code: Alles auswählen

f=file(filename_PS_ctr+i,'r')
f_lines = f.readlines()	
f_list = list(islice(f_lines, 273 ))
	
zeile = f_list[25-1]
stelle = zeile.index('=')	
p_in = zeile[stelle+2:stelle+16]
print p_in
	
zeile = f_list[26-1]
stelle = zeile.index('=')	
p_ex = zeile[stelle+2:stelle+16]
print p_ex
Verwenden von genauen Stellen ist etwas unsicher, da die Dateien zwar gleich aussehen, sich jedoch in der ersten Zeile der Dateien Zahlen änderen (von einstellig zu zweistellig und umgekehrt).

Danke nochmal für den Tip
BlackJack

Mit dem Quelltext sparst Du jetzt aber weder Zeit noch Speicherplatz beim einlesen der Datei. In der zweiten Zeile liest Du mit `readlines()` die *komplette* Datei in den Speicher. Wie gesagt, falls die Dateien nicht riesig sind, oder Dir das Programm so wie's jetzt ist nicht zu langsam vorkommt, kannst Du's auch einfach dabei belassen und die nächste Zeile mit `f_list` rauswerfen. Für eine Liste die sich schon im Speicher befindet ist die `list()`/`islice()`-Kombination unnötig kompliziert und langsam.

Und wie sehen die Zeilen denn aus? Bezeichner gefolgt von einem Gleicheitszeichen, gefolgt vom Wert? Dann kannst Du jetzt auch weiter gehen und Dich auch in den Zeilen nicht mehr auf feste Positionen verlassen.

Code: Alles auswählen

In [20]: 'identifier = value\n'.split('=', 1)
Out[20]: ['identifier ', ' value\n']

In [21]: 'identifier = value\n'.split('=', 1)[1]
Out[21]: ' value\n'

In [22]: 'identifier = value\n'.split('=', 1)[1].strip()
Out[22]: 'value'
Und wenn Du dann noch den ganzen Weg gehen willst, dann kannst Du mit einer Liste der Bezeichner in der Hand die Zeilen einzeln durchgehen und prüfen ob ein gewünschter Bezeichner in der Zeile vorkommt und wenn ja, den Wert aus der Zeile holen. Dann dürften sich sogar die Zeilennummern ändern ohne das Dein Skript "kaputtgeht".
Blackgarfield
User
Beiträge: 5
Registriert: Mittwoch 30. August 2006, 16:11
Wohnort: Cottbus

hmmm Blackjack,

du kannst recht haben, anbei mal ein Dateifragment:

EWA 20070 COMP HP Stage 7 Rotor Section 1 Version 622

CHORD [mm] = 23.566487516
CHORDM [mm] = 18.086097112
XMAX [mm] = 76.951977992
MERID. VELOCITY [m/s] = 215.030424496
ABS. VELOCITY [m/s] = 224.827384081
ABS. VELOCITY TANG. [m/s] = -65.645023984
REL. VELOCITY [m/s] = 355.382002751
REL. VELOCITY TANG. [m/s] = 282.945726988
TOT. TEMPERATURE [K] = 653.873099872
REL.TOT. TEMP. [K] = 689.551514000
ROTHALPIE/CP [K] = 632.316700664
REL.TOTALPRESSURE [KPa] = 1483.930420000
ABS.TOTALPRESSURE [KPa] = 1219.222055982
EXTRALOSS [-] = 0.000000000
INLET REL. MACH NO. [-] = 0.713795000
OUTLET REL. MACH NO. [-] = 0.490250000

ich brauche eine gewisse Zeile und davon den Wert. Dabei kann der Wert auch negativ sein. Ausserdem gibt es in dem File noch Zahlenblöcke (z.B. 3 Spalten a 100 Zeilen), wovon ich nur den zweiten Block bzw. die zweite Spalte brauche. Bisher habe ich alle Blöcke einfach umgespeichert und die Daten mit einen anderen Programm weiterverarbeitet.
Ja ich weis nicht sauber aber ich bi n ja auch kein Informatiker..... ;-)
Antworten