UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa4

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
psamulat
User
Beiträge: 1
Registriert: Dienstag 8. Oktober 2024, 13:32

Hallo,
in dem nachfolgenden Skript wird die eine Fehlermeldung erzeugt:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa4 in position 0: invalid start byte

0xa4 sollte aber im UTF-8 ein "ä" sein. Was mache ich falsch?

##

a=0
b=""
with open("REZEPTE.BNK", "rb") as f:
while (byte := f.read(1)):
a=a+1
if a<100:
print(byte)
if byte >=b' ':
b=b + byte.decode()
else:
print(b)
b=""

print(a)
Sven_TKLOOP
User
Beiträge: 12
Registriert: Freitag 16. August 2024, 14:10

UTF-8 nutzt ASCII
Alles über 127 muss bei UTF-8 also durch zwei Bytes, oder mehr, dargestellt werden.
0xa4 sind 164 und deswegen denkt UTF-8 dass das ein Folgebyte / Fortsetzungsbyte ist, weil 164 größer als 127 ist und somit kein ASCII Zeichen ist... bedeutet kann nicht alleine stehen
In UTF-8 ist ein ä "0xC3 0xA4"
Hier kannst du dir die gesamten Zeichen anschauen: https://www.utf8-zeichentabelle.de/

Da ich in dem Bereich nicht der fitteste bin wäre mein Tipp die Datei mal direkt mit einer anderen Codierung zu öffnen

Vielleicht klappt das ja

Code: Alles auswählen

with open("REZEPTE.BNK", "r", encoding="windows-1252") as f:
    content = f.read()
Vielleicht enthält die Datei auch andere Codierungen, so gut kenne ich mich damit aber nicht aus.

Versuch einfach mal die Codierung zu wechseln, vielleicht auch irgendeine ISO-8859-1 (keine Ahnung was es da alles gibt und wie die aussehen) probieren.
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Es scheint so, als ob Du aus einer Binärdatei irgendwelche Strings herauspuhlen willst. Dazu solltest Du aber die Bytes, die Du jetzt einfach ignorierst auch interpretieren.
Was ist das für eine Datei und in welchem Format?

Zum Code: statt jedes Byte einzeln zu lesen, könnte man die 100 Byte direkt lesen und sie mit einer for-Schleife abarbeiten:

Code: Alles auswählen

with open("REZEPTE.BNK", "rb") as f:
    data = f.read(100)

byte_string = []
for byte in data:
    if byte >= 32:
        byte_string.append(byte)
    else:
        string = bytes(byte_string).decode(CORRECT_ENCODING)
        print(string)
        byte_string = []
oder noch einfacher mit einem regulären Ausdruck:

Code: Alles auswählen

for byte_string in re.findall(b"[^\x00-\x1f]+", data):
    string = bytes(byte_string).decode(CORRECT_ENCODING)
    print(string)
Benutzeravatar
__blackjack__
User
Beiträge: 13998
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@psamulat: Ist vermutlich nicht gewollt, aber das Leerzeichen wird von Deinem Code auch gefiltert weil:

Code: Alles auswählen

In [60]: b" " > b"  "
Out[60]: False
`a` wäre dann wohl die Länge der tatsächlich gelesenen Daten.

Code: Alles auswählen

#!/usr/bin/env python3
import re


def main():
    with open("REZEPTE.BNK", "rb") as file:
        content = file.read(100)

    for match in re.finditer(rb"[^\x00-\x1f]+", content):
        print(match.group(0).decode("utf-8"))

    print(len(content))


if __name__ == "__main__":
    main()
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Antworten