Schei� encoding

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.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Ich suche einen weg, strings in bytes umzuwandeln (und umgekehrt), dabei sollte es egal sein welche Zeichen im String enthalten sind.
Und ich meine nicht:

Code: Alles auswählen

str(b'\x00t\x00e\x00s\x00t', 'ASCII')
und

Code: Alles auswählen

bytes('test', 'ASCII')
weil das mit Zeichen nicht geht, die einen größeren wert als 128 haben, was ich brauche wäre entweder eine Funktion für strings in bytes (umgekehrt hab ich schon eine), oder eine passende Codierung, aber UCS-2, kennt Python, nicht ...

(und da hauptsächlich 2.x user probleme mit encoding haben: ich hab 3.x)
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
BlackJack

@Py-Prog: Nimm eine der UTF-Kodierungen, die können alle Zeichen auf Bytes abbilden. Ich würde UTF-8 verwenden. Das ist — zumindest bei Texten wo die ASCII-Untermenge einen wesentlichen Anteil ausmacht — nicht zu aufgeblasen, und lässt sich auch in anderen meisten anderen Kodierungen angezeigt, zumindest noch halbwegs lesen/verstehen.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Glaubst du das hätte ich nicht versucht? Ich hab's grad noch mal getestet und dann kommt:

Traceback (most recent call last):
File "C:\Python31\lib\socketserver.py", line 558, in process_request_thread
self.finish_request(request, client_address)
File "C:\Python31\lib\socketserver.py", line 320, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Python31\lib\socketserver.py", line 614, in __init__
self.handle()
File "C:\Dokumente und Einstellungen\Py-Prog\Desktop\XXX.py", line 29, in handle
self.packet = bytes_to_str(self.recv_from_client)
File "C:\Dokumente und Einstellungen\Py-Prog\Desktop\XXX.py", line 12, in bytes_to_str
return str(bytes_, 'UTF-8')
UnicodeDecodeError: 'utf8' codec can't decode byte 0xfe in position 0: unexpected code byte
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
BlackJack

@Py-Prog: Und auf der anderen Seite hast Du auch UTF-8 kodiert? Das kann nicht sein.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Nach der (inoffiziellen) Dokumentation bräuchte ich UCS-2, das wird von Python aber nicht unterstützt, ... und das Protokoll kann ich nicht ändern wie es mir Passt.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
deets

Ucs2 ist eine teilmenge von UTF-16, also kannst du das benutzen.

http://en.m.wikipedia.org/wiki/UTF-16
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Habs probiert, das Ergebnis:
UnicodeDecodeError: 'utf16' codec can't decode byte 0x00 in position 0: truncated data
(der rest wie oben)
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
BlackJack

@Py-Prog: Dann musst Du vielleicht berücksichtigen in welcher Reihenfolge die Bytes kommen und explizit zwischen UTF-16 Big oder Little Endian wählen. Interessanterweise scheint bei der letzten Ausnahme, die Du davor gezeigt hast eine „byte order mark” (BOM) gesendet zu werden. Bei dem Beispiel im ersten Beitrag gibt es die nicht.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Dein obiger String wird von UTF-16BE problemlos dekodiert:

Code: Alles auswählen

>>> '\x00t\x00e\x00s\x00t'.decode('UTF-16BE')
u'test'
Mit BOM sollte UTF-16 automatisch die richtige Reihenfolge rausfischen:

Code: Alles auswählen

>>> '\xfe\xff\x00t\x00e\x00s\x00t'.decode('UTF-16')
u'test'
Aber Achtung, sollest Du hier BE einstellen und ein BOM wird mitgeschickt, so wird es nicht mehr als BOM behandelt und mit ausgegeben.

Mehr dazu siehe codecs-Modul.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

jerch hat geschrieben:Dein obiger String wird von UTF-16BE problemlos dekodiert:

Code: Alles auswählen

>>> '\x00t\x00e\x00s\x00t'.decode('UTF-16BE')
u'test'
Welchen teil des Satzes "Und ich meine nicht:" hast du nicht verstanden? :roll:
Diese "Beispiele" haben nichts mit dem Programm zu tun, die hab ich blos deswegen geschrieben das keiner meint ich weiß nicht wie das (normalerweise) geht, und dann genau das noch mal schreibt.

Und ehrlich gesagt hab ich nicht geschnallt was ihr in den letzten beiden Beiträgen meint.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
lunar

@Py-Prog: Lies auf Wikipedia nach, wie UCS-2 und UTF-16 aufgebaut sind. Dort wird dann bestimmt auch erklärt, was es mit der Byte-Reihenfolge bei UTF-16 und der BOM auf sich hat.
deets

Py-Prog hat geschrieben:
jerch hat geschrieben:Dein obiger String wird von UTF-16BE problemlos dekodiert:

Code: Alles auswählen

>>> '\x00t\x00e\x00s\x00t'.decode('UTF-16BE')
u'test'
Welchen teil des Satzes "Und ich meine nicht:" hast du nicht verstanden? :roll:
Kaum wieder da, schon gleich die Attitüde mitgebracht... welchen Teil von jerch's Beispielen hast *DU* nicht verstanden? Deine Daten sind UTF-16 oder UCS2-kodiert, aber ohne BOM - also musst du das wahlweise davor packen, oder als Teil des Dekoders mitgeben. So einfach ist das. Wenn man weiss, was man tut... siehe unten.
Py-Prog hat geschrieben:[
Und ehrlich gesagt hab ich nicht geschnallt was ihr in den letzten beiden Beiträgen meint.
Na, dann waere eine freundliche Nachfrage statt anmassender "welchen teil des Satzes hast du nicht verstanden"-Aeusserungen angebrachter, oder?
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Py-Prog
Wie Dir vllt. entgangen ist, habe ich nicht versucht, den Beispielstring mit ASCII zu dekodieren, so wie Du in Deinem "Ich meine nicht"-Teil. Da kommt nämlich im Sinne einer Zeichenrepräsentation totaler Käse raus, auch ohne Bytes über 0x7f.

Zu Deiner Behauptung 2.x User haben hauptsächlich Probleme mit encoding - das mag fürs Forum stimmen, da hier die meisten wahrscheinlich noch 2.x einsetzen und dort am ehesten früher oder später in das Problem laufen. Das ist aber weniger eine direkte Folge aus Version 2.x, da Du datenverarbeitungstechnisch mit allen Sprachen diese transcoding-Probleme hast. Vllt. würde das Verständnisproblem geknackt, wenn die Sprachen zu einem Typenmodell für die encodings wechseln würden. Python macht das ja in gewisser Weise mit Unicode- vs. Bytestring vor (im Speicher werden unicode-Sequenzen als UCS2 oder UCS4 abgelegt).
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Ich hab mir nochmal den Login angesehen:

Code: Alles auswählen

Client: b'\x02\x00\x1d\x00L\x00a\x00p\x00i\x00s\x00L\x00a\x00z\x00u\x00l\x00i\x00;\x001\x00.\x001\x001\x00.\x001\x001\x00.\x001\x001\x001\x00:\x001\x001\x001\x001\x001'
Server: b'\x02\x00\x01\x00-'
Client: b'\x01\x00\x00\x00\x1d\x00\x0b\x00L\x00a\x00p\x00i\x00s\x00L\x00a\x00z\x00u\x00l\x00i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Server: b'\x01\x00\r\xebU\x00\x00\x00\x07\x00d\x00e\x00f\x00a\x00u\x00l\x00t\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x10\x06\x00\x00+t\x00\x00\x00\x14\x00\x00+#\xca\x00\x00\x00\x00\x04\x00\x00\x00\x00\x03|\xfc2\x03\x00\x08\x00\xa7\x005\x00\xa7\x006\x00\xa7\x004\x00\xa7\x005\x03\x00\x08\x00\xa7\x004\x00\xa7\x005\x00\xa7\x003\x00\xa7\x004'
und da ist mir aufgefallen das das erste byte nicht \x00 ist. Jetzt hab ich vorne noch \x00 angehängt:

Code: Alles auswählen

>>> b'\x00\x02\x00\x1d\x00L\x00a\x00p\x00i\x00s\x00L\x00a\x00z\x00u\x00l\x00i\x00;\x001\x00.\x001\x001\x00.\x001\x001\x00.\x001\x001\x001\x00:\x001\x001\x001\x001\x001'.decode('UTF_16BE')
'\x02\x1dLapisLazuli;1.11.11.111:11111'
Es funktioniert, aber wenn dieses \x00 am Anfang stehen muss damit man es decodieren kann, wieso wird es dann nicht mit übertragen?
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Ok, es ist doch noch nicht gelöst, ich bekomme immer noch eine Fehler Meldung, aber nicht gleich am Anfang wie vorher.

Code: Alles auswählen

b'\x00\x01\x00\x00\x00\x1d\x00\x0b\x00L\x00a\x00p\x00i\x00s\x00L\x00a\x00z\x00u\x00l\x00i\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Wenn ich das versuche zu decodieren:
UnicodeDecodeError: 'utf16' codec can't decode byte 0x00 in position 42: truncated data
600 Beitrag
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
BlackJack

@Py-Prog: Kann es sein, dass nicht alles in dem Protokoll Zeichen sind, sondern dass da zusätzlich auch noch Binärdaten enthalten sind!?
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Ja das könnte sein, aber \x01 ist der Login, und ich glaube da sollte keine Binärdaten enthalten sein.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Von Minecraft war ja bisher noch nie die Rede... und auf den ersten Blick sieht das für mich definitiv nach einem Binärformat aus! Gibt es dafür keine fertige Python-Lib, die Du für die Kommunikation verwenden kannst? Ansonsten solltest Du Dich mit speziellen Libs zum Erstellen eines Parsers für binäre Protokolle befassen, z.B. construct.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Py-Prog: Natürlich sind da Binärdaten enthalten. Das steht doch sogar in der Protokollbeschreibung die Du verlinkt hast. Das fängt mit der \0x01 selbst an, die ja nicht Bestandteil der Zeichenkette ist, gefolgt von einer als ``int`` kodierten Versionsnummer für das Protokoll, und dann kommt erst die Zeichenkette. Wobei die auch nicht sofort mit Zeichen beginnt, sondern mit einem 16-Bit-Wert der die Länge angibt: http://mc.kev009.com/Data_Types
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Hyperion hat geschrieben:Von Minecraft war ja bisher noch nie die Rede... und auf den ersten Blick sieht das für mich definitiv nach einem Binärformat aus! Gibt es dafür keine fertige Python-Lib, die Du für die Kommunikation verwenden kannst? Ansonsten solltest Du Dich mit speziellen Libs zum Erstellen eines Parsers für binäre Protokolle befassen, z.B. construct.
Ich kann das leider nicht hernehmen weil das nur für 2.x ist.

@BlackJack wenn ich das jetzt richtig verstanden habe
\x03\x00\x05\x00h\x00a\x00l\x00l\x00o
Dann steht das rote für eine chat Nachricht, das blaue ist die Länge, und das grüne ist der Text, denn ich decodieren kann.
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Antworten