Inhalt aus einer Datei lesen , nur Mist bekomme

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
Gast

Dienstag 10. Januar 2006, 15:48

Hallo zusammen!

Ich habe ein Problem beim Dateilesen:

wenn ich die Datei nicht explizit als UTF8 gespeichert habe, bekomme mit
fh = file("filename", "r")
txt = fh.readline() # richtig String!

Aber mit UTF8, bekomme ich

'\xef\xbb\xbf'
vor dem richtigen Text aus der ersten Zeile.

Ist das die magische Nummer für den Dateityp?

Kann ich irgendwie den richtigen Inhalt bekommen?

Tipps benötigt!

Boostpy
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 10. Januar 2006, 16:49

Anonymous hat geschrieben:Ist das die magische Nummer für den Dateityp?
Das ist der Byte Order Mark (BOM)
Englischer Wikipadia Artikel zum Thema BOM hat geschrieben:The UTF-8 representation of the BOM is the byte sequence EF BB BF, which appears as the ISO-8859-1 characters "" in most text editors and web browsers not prepared to handle UTF-8.

Code: Alles auswählen

In [1]: bom = '\xef\xbb\xbf'
In [2]: print bom

My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 10. Januar 2006, 16:54

Schau mal in die unicode FAQ: http://p-nand-q.com/python/unicode_faq.html

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Gast

Dienstag 10. Januar 2006, 19:08

hi Leonidas & Jens!

Danke für den Hinweis und Link.

zu Jens: Ich habe bei Pylucid Forum geschrieben. Ich habe immer noch nicht geschafft, dort wird ein Post auf dich wartet.

BTW, ich habe keinen Mail geschrieben, sondern irgendwo bei Pylucid Forum noch ein Post vorhanden, nur mit fast identischen Inhalt :cry:
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 10. Januar 2006, 20:49

Anonymous aka Boostpy hat geschrieben:zu Jens: Ich habe bei Pylucid Forum geschrieben. Ich habe immer noch nicht geschafft, dort wird ein Post auf dich wartet.

BTW, ich habe keinen Mail geschrieben, sondern irgendwo bei Pylucid Forum noch ein Post vorhanden, nur mit fast identischen Inhalt :cry:
Ich hab dir geantwortet... Aber hier auch nochmal: Meld dich bitte an, damit man besser zuordnen kann, wer was geschrieben hat :) Außerdem kannst du eMail-Benachrichtigung erhalten, wenn jemand auf deinen Beitrag geantwortet hat! Sehr Pratisch...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 16. Januar 2006, 17:14

Schau dir mal den Quellentext von \Lib\codecs.py an... Da sind die BOM-Marken zu sehen ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Montag 16. Januar 2006, 17:55

Wenn Du so auf die Datei zugreifst willst Du einen:

http://www.python.org/doc/2.4.2/lib/str ... jects.html

StreamReader, der das Datei-Objekt kapselt. Der kümmert sich automatisch um die BOM (falls eine vorhanden ist).

Weitere Dokumentation unter obigem Link, und auch Beispiele.

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 16. Januar 2006, 18:04

modelnine hat geschrieben:StreamReader, der das Datei-Objekt kapselt. Der kümmert sich automatisch um die BOM (falls eine vorhanden ist)
Sollte man wohl generell benutzten, wenn man text-Dateien verarbeitet, was?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Montag 16. Januar 2006, 18:07

Wenn die Dateien von einem Unicode-Editor ausgespuckt werden der eine BOM schreibt (bei UTF-8 eigentlich nicht nötig!), dann ja.

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 16. Januar 2006, 18:22

Naja, aber schaden kann es wohl nicht immer StreamReader zu nehmen, statt file, oder???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Montag 16. Januar 2006, 18:25

Ganz definitiv: ja. Sobald Du mit Eingabe konfrontiert bist die nicht byte-strings sind sollte man immer einen StreamReader nehmen, egal ob man das dekodieren selbst machen kann oder nicht.

StreamReader liefern auch automatisch unicode-strings zurück (bei der entsprechenden Auswahl einer Kodierung die unicode strings erzeugt, gibt ja auch andere), und können die Eingabe zeichenweise verarbeiten, was Du mit einem normalen read() aus einer Datei nicht kannst, weil Du Dich wenn Du dann ein .decode("<blah>") machst zwischen zwei aufeinanderfolgenden Bytes für ein Zeichen befinden könntest.

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 16. Januar 2006, 18:27

Kannst du mal ein kurzes Beispiel posten?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Dienstag 17. Januar 2006, 11:25

Beispiel:

schreiber.py

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-
import codecs

f = file("test.dat","w")
s = codecs.getwriter("utf16")(f)

s.write(u"Heute geht es mir gut, weil ich äöü schreiben darf!")
f.close()
leser.py

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-
import codecs

f = file("test.dat","r")
s = codecs.getreader("utf16")(f)

# Dieses encode sollte eigentlich unnötig sein, da zumindest bei mir Python mein
# Terminal automatisch als latin-15 erkennt; kann aber ab und an wenn die
# automatische Erkennung des Terminal-Charsets versagt nötig werden und hat
# nix mit dem Lesen zu tun, sondern nur mit dem Ausgeben per print.
print s.read().encode("iso-8859-15")

f.close()
Dass ich im obigen Beispiel utf16 gewählt habe als codec ist eigentlich nur deswegen interessant weil der StreamWriter eine BOM immer notwendigerweise schreibt, das bedeutet man auf jeden Fall eine Eingabedatei mit BOM hat.

Wichtig zu bemerken ist weiterhin dass StreamReader und -Writer nur das allernötigste vom file-Interface implementieren: read(), readline(), readlines(), reset() respektive write(), writeline(), reset().

reset() wird dazu benötigt um den Zustand eines Decoders zurückzusetzen. Das kann man zum Beispiel machen wenn in einem bestimmten Stream eine Neusynchronisierung nötig ist wegen defekter Zeichen, o.Ä. Hierzu sind auch die Argumente für den Constructor des StreamReader/Writer interessant.

Am besten guckt Ihr Euch die Doku an:

http://docs.python.org/lib/stream-reader-objects.html
http://docs.python.org/lib/stream-writer-objects.html

und als Menge der standardmäßig vorhandenen encodings:

http://docs.python.org/lib/standard-encodings.html

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 17. Januar 2006, 11:29

Die Zeile print s.read().encode("iso-8859-15") dürfte wegen dem # -*- coding: iso-8859-15 -*- unnötig sein, denke ich...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Dienstag 17. Januar 2006, 11:31

Die Zeile print s.read().encode("iso-8859-15") dürfte wegen dem # -*- coding: iso-8859-15 -*- unnötig sein, denke ich...
Nein, ist sie nicht. Das File-Encoding deiner Eingabedatei macht es nur unnötig "blah äöü".decode("iso-8859-15") im ersten für u"blah äöü" zu schreiben. Sie hat rein gar nichts damit zu tun wie das ganze nachher ausgegeben wird, das ist von sys.getdefaultencoding() abhängig.

--- Heiko.
Antworten