Programm fertig, aber Schleife einbauen klappt nicht

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.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Bin zur Zeit mit meinem Latain etwas am Ende. Als Neuling in Python mit ansonsten geringen Programmierkenntnissen kam ich bisher recht gut voran. Hab mein Programm für einen Durchlauf hinbekommen und wollte nun eine Schleife einbauen um dem Ganzen den eigentlichen Sinn zu geben.

Ich hoffe der Code ist nicht zu durcheinander. Also folgendes wird gemacht. Ich öffne zuerst eine Datei und les mir aus der ersten Zeile die ersten 17 Spalten als neuen Dateinamen raus. Danach schließe ich die Datei wieder und öffne sie erneut. Das war nötig, weil ich ansonsten zwar auch die 17 Spalten als Dateiname bekam, diese Spalten dann aber auf einmal in der Datei fehlten. Wende also wohl einen kleinen "Bauerntrick" an. Das geht vermutlich auch anders, aber so erfüllt es ja auch seinen Zweck.
Nachdem ich die Datei ausgegeben habe, erzeuge ich eine neue Datei, die den Dateinamen der 17 Spalten hat wie oben beschrieben.Eingelesen wird dabei die Zeile 0 bis 224.
Nun habe ich Dateien wo ich alle 224 Zeilen das gleiche machen muss. Dafür habe ich mir eine for Schleife überlegt, bei dem ich dem Programm sage, dass es mir immer das "i" aus der Range nehmen soll. Zumindest vermute ich dass ich das dem Programm gesagt habe. Also erst 0-224, dann 224-448 usw.
Klappen tut das aber nicht so wirklich. Er schmeißt mir dann eben alle 448 Zeilen in eine Datei statt zwei mit dem Dateinamen der ersten Zeile.

Das drüfte daran liegen, dass ich dem Programm noch nicht gesagt habe, dass er den Dateinamen ja für Datei 1 aus Zeile 0 und für Datei 2 aus Zeile 224 usw. nehmen muss. Ich finde dafür keinen Syntax wie man bei readline neben der Spaltenangabe noch die Zeilenangabe angeben kann und das Ganze dann durch eine Variable für eine Schleife ersetzen kann.

Hier ist mal der Code. Momentan habe ich die Schleifen ausgeschaltet.

Code: Alles auswählen

# Defintion von Variablen

# Definition von k (Spaltenlaenge fuer den Dateinamen)
k = 17

# Definition von i (Anzahl der Zeilen pro Bild)
i = 224

# Definition von j (Startpunkt des Bildes)
j = i - 224
#j = 0

#for i in range (0,672,224): # hier fehlt noch die Zeilenangabe wo die Spalten als Dateiname verwendet werden müssen

# öffnet entsprechende Datei
fd = file("C:/Test/0601010001", "rb")

# Defintion Dateiname
Dateiname = fd.readline (k)

# schließt Datei wieder
fd.close()

# öffnet entsprechende Datei
fd = file("C:/Test/0601010001", "rb")

# Ließt die gesamte Datei ein
inhalt = fd.readlines()

# schließt Datei wieder
fd.close()

# Schreibt Inhalt in Shell
#print inhalt

#for i in range(0,672,224):  

# Erzeugt neue Datei
fd_out = file(Dateiname, "w")

# Schreibt Inhalt in neue Datei
fd_out.writelines(inhalt[j:+i])

# Schließt erzeugte Datei wieder
fd_out.close()
BlackJack

Wenn da mehrere Datensätze in der Datei sind, die gleich behandelt werden sollen, dann solltest Du den Ersten eben nicht besonders behandeln, sondern eine Schleife schreiben, die jeweils einen Datensatz verarbeitet.

Code: Alles auswählen

• Datei öffnen
• Solange noch Daten da sind:
  - Zeile mit Namen lesen.
  - Die nächsten 224 Zeilen verarbeiten.
• Datei schliessen.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Also du meinst, das Programmkonzept nochmal umwerfen?
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Ungetestet, und falls ich das Problem richtig verstanden habe:

Code: Alles auswählen

infile = open("C:/Test/0601010001", "rb")

while True:
    erstezeile = infile.readline()
    if not erstezeile: break #dateiende erreicht

    outfile = open(erstezeile[:17], "wb")
    outfile.write(erstezeile)
    for i in range(1, 244):
        outfile.write(infile.readline())
    outfile.close()


infile.close()
Edit: Bugfixes.
Copy & Paste direkt vorm Mittagessen ist nicht gut...
Zuletzt geändert von Rebecca am Donnerstag 17. Juli 2008, 12:56, insgesamt 1-mal geändert.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Erstmal danke für die Tipps.

Leider hakt es weiterhin.

Traceback (most recent call last):
File "C:/Test/test_neu.py", line 7, in <module>
outfile = file("erstezeile[:17]", "rb")
IOError: [Errno 2] No such file or directory: 'erstezeile[:17]'

Irgendwie passt Python hier was nicht. Den Fehler hatte ich bei mir gestern auch schon gehabt.
Mir ist aber nicht ganz klar was er hier zu meckern hat. "erstezeile" ist doch weiter oben definiert.
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

Du musst als 2ten Parameter 'w' übergen, damit Python die datei schreiben kann (write).
Du öffnest die Datei nur mit Read/Binary. Probier mal 'wb'.

MfG,
CracKPod
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Rebecca hat geschrieben:Ungetestet, und falls ich das Problem richtig verstanden habe:

Code: Alles auswählen

    outfile = open("erstezeile[:17]", "rb")
    outfile.write(erstezeile)
    for i in range(1, 244):
        outfile.write(infile.readline())
    outfile.close()
Was soll das denn tun? Oo
Es will eine Datei "erstezeile[:17]" zum Lesen im Binärmodus öffnen und will dann 243 Zeilen von infile in die zum lesen geöffnete outfile schreiben? Oo
lunar

Die Anführungszeichen um "erstezeile[17:]" in Zeile 7 entfernen.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Ja, die Idee hatte ich auch schon.

Dann ändert sich nur die Fehlermeldung in folgendes um:

Traceback (most recent call last):
File "C:/Test/test_neu.py", line 7, in <module>
outfile = open(erstezeile[:17], "rb")
IOError: [Errno 2] No such file or directory: '\x04PF01000510637010'
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

zeig doch mal den relevanten Teil einer solchen Datei.

Das mit den 17 Spalten komm mir komisch vor Oo
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Chris82 hat geschrieben:

Code: Alles auswählen

outfile = open(erstezeile[:17], "rb")
IOError: [Errno 2] No such file or directory: '\x04PF01000510637010'
Du mußt 'wb' benutzen, wenn du im binären Modus schreiben willst. Hat Crazed weiter oben schon geschrieben.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Also wie schon ganz oben beschrieben, habe ich eine Datei, in der Bilder im Binärcode sind. Alle 224 Zeilen fängt ein neues Bild an. Nun möchte ich für jedes Bild eine einzelne neue Datei erstellen. Der Dateiname soll dabei immer aus 17 Spalten der ersten Zeile des jeweiligen Bildes bestehen.
Diese sieht so aus "PF010005106370106", also dieser Teil ist nicht binär.
Klappt wie gesagt auch für eine Datei, aber die Schleife dafür hab ich nicht richtig hinbekommen.

Übrigens "wb" klappt auch nicht :(

Traceback (most recent call last):
File "C:/Test/test_neu.py", line 7, in <module>
outfile = open(erstezeile[:17], "wb")
IOError: [Errno 2] No such file or directory: '#\r\n'
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Offensichtlich enthaelt die erste Zeile nicht das, was du denkst. In diesem Fall besteht sie nur aus einem # (Koennte z.B. eine Python-Datei sein... :P) Ich kann halt ohne eine Beispiel-Inputdatei das Programm nicht selbst testen, mal davon abgesehen, dass ich am Beispiel viel besser verstehe.
Zuletzt geändert von Rebecca am Donnerstag 17. Juli 2008, 13:21, insgesamt 1-mal geändert.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Also ich habe gerade nochmal rumprobiert. Es wird zwar die erste Datei erzeugt, auch mit richtigem Dateinamen, aber das wars dann.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Rebecca hat geschrieben:Offensichtlich enthaelt die erste Zeile nicht das, was du denkst. In diesem Fall besteht sie nur aus einem # (Koennte z.B. eine Python-Datei sein... :P) Ich kann halt ohne eine Beispiel-Inputdatei das Programm nicht selbst testen, mal davon abgesehen, dass ich am Beispiel viel besser verstehe.
Also im Prinzip habe ich nichts anderes als eine Textdatei (.txt). Eben mit dem kleinen Unterschied, dass bis auf die obersten Zeilen ein Binärcode in der Datei ist, aber das ist kein Problem.

Der Durchlauf einer einzelnen Sequenz klappt ja reibungslos. Das Problem ist einfach die Schleife. Sobald ich zwei Sequenzen habe, wo mir zwei Dateien aufgeworfen werden sollen, schreibt er mir alle Daten weiterhin in eine Datei. Python erzeugt also keine zweite Datei.
BlackJack

Das kann bei Rebecca's Quelltext, nach Berichtigung der beiden Fehler bei `open()`, nur passieren, wenn in der Datei immer der gleiche Dateiname steht.

Und da landen dann auch nicht alle Daten drin, sondern nur die des letzten Schleifendurchlaufs.

Allerdings werde ich das Gefühl nicht los, dass Du das Dateiformat nicht richtig beschrieben hast. Wenn nach der ersten Zeile Binärdaten kommen, wie sehen die denn aus? Das ist schon eigenartig, wenn Binärdaten durch Zeilenumbrüche in Zeilen aufgeteilt werden, weil in der Regel da ja *alles* drin vorkommen kann, inklusive das Byte, was einen Zeilenumbruch darstellt. Wie soll man dass dann von den anderen unterscheiden?

Wie sieht denn die Spezifikation des Formats genau aus? Eine Beispieldatei wäre super.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Ich glaube den Fehler gefunden zu haben. Python meckert zwar immer noch bei Zeile 7, aber jetzt führt es alles korrekt aus, zumindest nach meinem ersten Überblick.
Ich lese jetzt von Spalte 1 bis 17 ein, also

Code: Alles auswählen

outfile = open(erstezeile[1:17], "wb")
Irgendwie war davor noch ein Binärzeichen, das hat Probleme gemacht.
Ein weiteres Problem was mir allerdings noch aufgefallen ist, weswegen die Sache nicht lief, ist dass einige Dateien 223 Zeilen bzw. 225 Zeilen hatten. Das ist dann natürlich ungünstig wenn ich immer davon ausgehen 224 Zeilen zu haben. Falls das nun keine Einzelfälle sind, habe ich ohnehin ein ziemlich großes Problem.

Nachdem ich diese beiden Problemquellen in meinem Testdatensatz beseitigt habe läuft es.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Herzlich willkommen beim Debuggen.
Mein erster Schritt wäre, mir mal mit

Code: Alles auswählen

print erstezeile[:17]
anzuschauen, was wirklich aus der Zeile ausgelesen wird.
EDIT: OK, hat sich erledigt...
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Also die ganze Sache scheint jetzt zu laufen. Meine Datenmenge sind leider so groß, dass ich nicht alles nachprüfen kann, aber es sieht gut aus.
Mir ist nur aufgefallen, anstatt von Zeile 1 bis 224 hätte ich von Zeile 1 Spalte 2 bis Zeile 225 Spalte 1 einlesen müssen. Das letzte Zeichen der Datei ist bei mir immer das erste, aber das scheint meinem Bild nichts auszumachen, von daher wohl egal.
An alle nochmal vielen Dank bei der Hilfe zur Lösung meines "kleinen" Programmierungsproblems.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Ich muss den Thread nochmal hoch holen.
Ungünstigerweise habe ich noch Daten, die ein Umbau des Skripts erfordern. Anstatt alle 225 Zeilen, beginnen nun Bilder mitten in der Datei. Also beispielsweise erst in Zeile 227 Spalte 150...
Nun muss ich mich an einem String orientieren. Der String EOT (End of Transmission) zeigt immer das Ende vom Bild an und direkt in der anschließenden Spalte beginnt ein neues Bild.
Der Unicode von EOT schaut so aus

Code: Alles auswählen

 u"\u0004"
Als Skript hatte ich diesen verwendet.

Code: Alles auswählen

infile = open("C:/Test/Testfile", "rb")

while True:
    erstezeile = infile.readline() 
    if not erstezeile: break 

    outfile = open(erstezeile[1:17], "wb")  
    outfile.write(erstezeile) 
    for i in range (1, 224): 
        outfile.write(infile.readline()) 
    outfile.close()
infile.close()
Wollte nun also nur die Änderung dort einbauen. Zerbrech mir aber schon den ganzen Tag darüber den Kopf ohne wirklich weiter zu kommen. Hauptproblem ist, dass ich keine Methode finde, die optional die Angabe eines Strings zulässt. Bei read() und readline() kann man nur die bytes optional angeben.
Ich suche also etwas wie:
Lese Inhalt von Datei bis zu String "x" und speichere Inhalt in neuer Datei und als Dateiname nimm die ersten 17 Spalten des eingelesen Inhalts.
Ich hatte den Skript schon mal etwas umgeändert, aber da kam nichts gescheites bei raus, weil eben read und readline keine Strings akzeptieren :evil:
Antworten