Seite 1 von 1

Steuerzeichen im String sorgen für Abbruch

Verfasst: Sonntag 4. März 2007, 11:04
von droptix
Ich durchwandere eine Datei zeilenweise. Am Ende von Zeile 39 steht ein [SUB]-Steuerzeichen. Das steht für "substitute character" und ersetzt ein Zeichen, das als nicht zulässig oder fehlerhaft erkannt wurde.

Mein Python-Skript bricht die Verarbeitung der Datei an dieser Stelle ohne Fehlermeldung ab. Wieso und wie kann ich das verhindern?

Ich weiß zwar nicht, wie es da rein gekommen ist, aber vielleicht hat es eine Bedeutung und muss auch nach meiner Dateiverarbeitung bestehen bleiben. Daher kann ich nicht pauschal alle mir komisch erscheinenden Zeichen entfernen.

Wie ich soeben festgestellt habe, liest Python die Datei nur bis Zeile 39, obwohl sie im Editor 457 Zeilen hat. Hier mal der Code:

Code: Alles auswählen

fileName = "spam.txt"
f = file(fileName)
lines = f.readlines()
f.close()
l = len(lines)
print "file got %d lines" % l
for lineNo in range(l):
	line = lines[lineNo]
	lineNo += 1
	print lineNo
Und die Ausgabe:

Code: Alles auswählen

file got 39 lines
1
2
3
…
37
38
39
Im Binärmodus scheint's zu gehen… alle Zeilen sind da. Wieso ist das so?

Verfasst: Sonntag 4. März 2007, 11:50
von BlackJack
Das Zeichen 26 (SUB, 0x1a, ^Z) bedeutet unter Windows in Textdateien, dass die Datei da zu Ende ist. Das ist unabhängig von der Programmiersprache, da kann Python also nix für, das Problem hättest Du in C genauso.

Das ist historisch bedingt. Unter CP/M, dem Vorgänger von DOS, gab's keine byte-genauen Längenangaben für Dateien sondern nur die Information wieviele Blöcke auf der Diskette oder Festplatte belegt sind. Da brauchte man dann eine Endmarkierung innerhalb des letzten Blocks einer Textdatei.

Du solltest also dafür sorgen das so "komische" Bytes nicht in Deinem Text auftauchen.

Re: Steuerzeichen im String sorgen für Abbruch

Verfasst: Sonntag 4. März 2007, 17:52
von sape
Im Binärmodus scheint's zu gehen… alle Zeilen sind da. Wieso ist das so?
Weil sie dann nicht im Textmodus gelesen wird, und dadurch das Dateiendezeichen für Textdateien nicht "interpretiert" wird.

1. Binärdateien sollte immer im Binärmodus geöffnet werden.
2. Textdateien sollten *fast* immer im Textmodus geöffnet werden.
3. Für Binärdateien gibt es **keine** Situationen wo es angebracht ist sie im Textmodus zu öffnen.

Was ich mich aber frage ist, wie kommen es das mehr als ein SUB-Steuerzeichen in deinen Textdateien vorhanden ist? Sind es vielleicht doch nur Binärdateien, die auch Klartext enthalten?

Verfasst: Sonntag 4. März 2007, 21:31
von droptix
Tja wo die das [SUB]-Zeichen herkommt ist mir auch ein Rätsel. Vielleicht ist das mal durch einen Fehler bei der Datenübertragung entstanden. Fakt ist aber, dass der Inhalt der Datei eigentlich reine Text-Daten sind, ähnlich wie in einer INI-Datei.

Ich mach das jetzt einfach binär. Dank eurer ausführlichen Beschreibung zu `os.linesep` & Co. war das ein Kinderspiel.

Verfasst: Sonntag 4. März 2007, 21:50
von EyDu
droptix hat geschrieben:Ich mach das jetzt einfach binär. Dank eurer ausführlichen Beschreibung zu `os.linesep` & Co. war das ein Kinderspiel.
Und was passiert, wenn ein Linux-System Windows-Daten bekommt ... :D?

Verfasst: Sonntag 4. März 2007, 22:41
von droptix
Die Datei wird von einem Tool erstellt, dass es nur unter Windows gibt… eigentlich muss es nur unter Windows weiter verarbeitet werden. Aber du hast recht :D ich hätte es ja gerne trotzdem plattformunabhängig.

Ich frag mal anders: sehr komfortabel erscheint mir `os.readlines()`. Woran erkennt denn die Funktion, an welchen Stellen ein Linebreak stattfindet? Am `os.linesep` oder wird das File-Objekt irgendwie analysiert? Anhand der Datei kann ja leider nicht erkannt werden, auf welchem System die erstellt wurde... und außerdem: ich kann mit dem richtigen Editor auch unter Windows Dateien erstellen, die lediglich auf "\n" enden (z.B. Notepad2).

Verfasst: Sonntag 4. März 2007, 23:15
von Leonidas
droptix hat geschrieben:Am `os.linesep` oder wird das File-Objekt irgendwie analysiert? Anhand der Datei kann ja leider nicht erkannt werden, auf welchem System die erstellt wurde...
Wenn man den hier verlinkten PEP 278 liest, dann kann man da rausfinden wie es im Moment gelöst ist:
PEP 278 hat geschrieben:This PEP discusses a way in which Python can support I/O on files which have a newline format that is not the native format on the platform, so that Python on each platform can read and import files with CR (Macintosh), LF (Unix) or CR LF (Windows) line endings.
Das heißt, dass der Zeilentrenner in Python der auf der betreffenden Platform nativ verwendete Zeilentrenner ist. Und ja, sowas ist unvorteilhaft wenn man mit Python unter Unices eine Windows-Textdatei editieren will oder andersrum. Daher auch PEP 278.