2015-05-14 6 views
5

Gegeben ein Strom von Bytes (Generator, Datei usw.) Wie kann ich ein einzelnes codiertes Zeichen utf-8 lesen?UTF-8-Zeichen aus Bytestream lesen

  • Diese Operation muss die Bytes dieses Zeichens aus dem Stream konsumieren.
  • Diese Operation darf keine Bytes des Streams verbrauchen, die das erste Zeichen überschreiten.
  • Diese Operation sollte auf jedem Unicode-Zeichen erfolgreich sein.

Ich konnte diesen Ansatz durch meine eigene utf-8 Dekodierungsfunktion rollen, aber ich würde nicht das Rad neu zu erfinden bevorzugen, da muß ich diese Funktionalität bin sicher, dass bereits an anderer Stelle utf-8 Strings analysieren verwendet werden.

Antwort

2

Wickeln Sie den Strom in eine TextIOWrapper mit encoding='utf8', dann rufen Sie .read(1) darauf.

Das geht davon aus, dass Sie mit einem BufferedIOBase oder etwas Ducktyp damit kompatibel sind (d. H. Hat eine read() Methode). Wenn Sie einen Generator oder Iterator haben, müssen Sie möglicherweise die Schnittstelle anpassen.

Beispiel:

from io import TextIOWrapper 

with open('/path/to/file', 'rb') as f: 
    wf = TextIOWrapper(f, 'utf-8') 
    wf._CHUNK_SIZE = 1 # Implementation detail, may not work everywhere 

    wf.read(1) # gives next utf-8 encoded character 
    f.read(1) # gives next byte 
+0

Hat 'TextIOWrapper' jede Pufferung tun (und dadurch raubend Bytes das erste Zeichen mehr als)? Wenn ich eine Datei 'f' nehme und sie' wrapped = TextIOWrapper (f, 'utf-8') '' wickle, liest das Aufrufen von 'wrapper.read (1)' gefolgt von 'f.read (1)' ein Byte viel weiter in den Stream als das Byte unmittelbar nach dem UTF-8-Zeichen. – arcyqwerty

+0

@arcyqwerty: 'TextIOWrapper' liest 2k Bytes gleichzeitig (' _CHUNK_SIZE'). Es verbraucht mehr Bytes als für das erste Zeichen notwendig. – jfs

+0

Gibt es alternativ eine Möglichkeit, rohe Bytes aus dem Wrapper 'TextIOWrapper' zu holen? – arcyqwerty