[Python-de] utf8 Problem mit Blockgrenzen
"Martin v. Löwis"
martin at v.loewis.de
Sam Aug 20 14:20:11 CEST 2005
Hans-Peter Jansen wrote:
> So, wie die Sache steht, bleibt mir wohl nix anderes übrig, als auf
> zeilenweise Verarbeitung auszuweichen, oder hat jemand eine bessere
> Idee?
In Python 2.4 kann der UTF-8-Decoder einen "partial mode":
decoded = codecs.utf_8_decode(encoded, "strict", 0)
Der letzte Parameter gibt an, ob es sich um das Ende der Eingabe
handelt. Falls nicht, und falls am Ende Bytes fehlen, gibt er
nur die dekodierten Zeichen und die Zahl der dazu konsumierten
Bytes an.
Man kann also schreiben
rest = ''
while True:
data = self.a2psfile.read(BUFSIZE)
if not data:
pfp.write(rest.decode("utf-8").encode("cp850"))
break
decoded, len = codecs.utf_8_decode(rest + data, "strict", 0)
rest = data[len:]
pfp.write(decoded.encode("cp850"))
In älteren Python-Versionen kann man das ineffizient nachbilden:
def utf_8_decode(data, errors, final):
if final:
return data.decode("utf-8", errors), len(data)
last = ord(data[-1])
if last < 0x80:
# ASCII, always single-byte
return data.decode("utf-8", errors), len(data)
if last >= 0xc0:
# last byte is lead byte
return data[:-1].decode("utf-8", errors), len(data)-1
# find lead byte
i = -2
while ord(data[i]) < 0xc0: i++
last = ord(data[i])
incomplete = False
if last < 0xe0:
# one extra byte, cannot be incomplete here
pass
elif last < 0xf0:
# two extra bytes, incomplete if we have only one
incomplete = (i != -3)
else:
# three extra bytes
incomplete = (i != -4)
if incomplete:
return data[:i].decode("utf-8", errors), len(data)+i
return data.decode("utf-8", errors)
Achtung: Dieser Code ist komplett ungetestet.
Ciao,
Martin