2016-02-02 2 views
-2

Je me demande comment puis-je convertir des caractères ISO-8859-2 (latin-2) (je veux dire des valeurs entières ou hexadécimales qui représentent l'encodage ISO-8859-2 caractères) en caractères UTF-8.Conversion entre ISO-8859-2 et UTF-8 en Python

Ce que je dois faire avec mon projet en python:

  1. Recevoir les valeurs hexagonales du port série, qui sont caractères de l'ISO-8859-2.
  2. Décodez-les, c'est - obtenez des chaînes "standard" python unicode.
  3. Préparez et écrivez le fichier xml.

En utilisant Python 3.4.3

txt_str = "ąęłóźć" 
txt_str.decode('ISO-8859-2') 
Traceback (most recent call last): File "<stdin>", line 1, in <module> 
AttributeError: 'str' object has no attribute 'decode' 

Le principal problème est toujours de préparer l'entrée valable pour la méthode « decode » (cela fonctionne en python 2.7.10, et thats celui que je suis en utilisant Dans ce projet). Comment préparer une chaîne valide à partir de la valeur décimale, qui sont des numéros de code Latin-2? Notez qu'il serait plus compliqué de recevoir des caractères utf-8 à partir du port série, grâce aux périphériques que j'utilise et aux limitations du protocole de communication.

Données d'échantillons, sur demande:

68632057 
62206A75 
7A647261 
B364206F 
20616775 
777A616E 
616A2061 
6A65696B 
617A20B6 
697A7970 
6A65B361 
70697020 
77F36469 
62202C79 
6E647572 
75206A65 
7963696C 
72656D75 
6A616E20 
73726F67 
206A657A 
65647572 
77207972 
73772065 
00000069 

Il s'agit quelques exemples de données. ISO-8859-2 poussé dans uint32, 4 caractères par int.

bits de code qui gère unboxing:

l = l[7:].replace(",", "").replace(".", "").replace("\n","").replace("\r","") # crop string from uart, only data left 
vl = [l[0:2], l[2:4], l[4:6], l[6:8]] # list of bytes 
vl = vl[::-1] # reverse them - now in actual order 

Pour obtenir la valeur entière de la chaîne hexagonale je peux simplement utiliser:

int_vals = [int(hs, 16) for hs in vl] 
+2

Il devrait être aussi simple comme: this_is_the_text_string.decode ('ISO-8859-2'), qui vous donne la chaîne unicode (au moins dans Python 3). – elzell

+1

Facile. Convertir de [hex en octets] (https://docs.python.org/2/library/binascii.html#binascii.a2b_hex), [décoder en latin-2] (https://docs.python.org/2 /library/stdtypes.html#str.decode), [encoder comme UTF-8] (https://docs.python.org/2/library/stdtypes.html#str.encode). Avez-vous des exemples de données? –

+1

Cependant, si vous voulez écrire du XML, pourquoi ne pas garder la valeur comme Unicode (donc décodée de ISO-8859-2), et la laisser à la bibliothèque XML pour encoder en UTF-8? –

Répondre

2

Votre exemple ne fonctionne pas parce que vous avez essayé de utilise un str pour contenir des octets. En Python 3, vous devez utiliser les chaînes byte.

En réalité, si vous utilisez pyserial alors vous en train de lire des chaînes d'octets de toute façon, que vous pouvez convertir au besoin:

with serial.Serial('/dev/ttyS1', 19200, timeout=1) as ser: 
    s = ser.read(10) 
    # Py3: s == bytes 
    # Py2.x: s == str 
    my_unicode_string = s.decode('iso-8859-2') 

Si vos données iso-8895-2 est en fait ensuite codé à représentation hexadécimale ASCII des octets, alors vous devez appliquer une couche supplémentaire de codage:

with serial.Serial('/dev/ttyS1', 19200, timeout=1) as ser: 
    hex_repr = ser.read(10) 
    # Py3: hex_repr == bytes 
    # Py2.x: hex_repr == str 

    # Decodes hex representation to bytes 
    # Eg. b"A3" = b'\xa3' 
    hex_decoded = codecs.decode(hex_repr, "hex") 
    my_unicode_string = hex_decoded.decode('iso-8859-2') 

vous pouvez maintenant transmettre my_unicode_string à votre bibliothèque XML favori.

+0

Merci pour la réponse. L'entrée réelle, que je reçois de uart, est affichée dans le premier message. Il n'y a rien que je puisse faire à ce sujet, juste ce que je peux lire de mon périphérique uart. Je sais, que ces caractères sont codés de la façon suivante: 1. Chaque octet ([0: 2], [2: 4] ...) est un nombre hexadécimal qui représente le caractère ISO-8859-2. 2. Sur chaque ligne, le premier octet est le dernier (LE/BE). 3. "00" indique que la chaîne d'entrée n'était pas divisible par 4. – user2046193

+0

ISO-8859-2 n'a pas d'octet endianess comme chaque caractère est seulement 1 octet, donc la chaîne doit également être encodée dans un uint32 aussi?Peut-être que vous pouvez partager du code du côté distant, car ce n'est pas clair du tout –

+0

Vérifiez le premier message. Malheureusement, je ne peux pas vous montrer tout le code à cause de l'accord IP. – user2046193

-1

Ce sujet est clos. Code de travail, qui gère ce qui doit être fait:

x=177 
x.to_bytes(1, byteorder='big').decode("ISO-8859-2") 
+0

Comment cela décode-t-il les données données? Vous obtenez des octets de PySerial, alors comment faites-vous cela dans un int? –

0

Données d'échantillon intéressantes. Idéalement, vos données d'échantillon doivent être une impression directe des données brutes reçues de PySerial.Si vous recevez effectivement les octets bruts sous forme de valeurs hexadécimaux à 8 chiffres, puis:

#!python3 
from binascii import unhexlify 
data = b''.join(unhexlify(x)[::-1] for x in b'''\ 
68632057 
62206A75 
7A647261 
B364206F 
20616775 
777A616E 
616A2061 
6A65696B 
617A20B6 
697A7970 
6A65B361 
70697020 
77F36469 
62202C79 
6E647572 
75206A65 
7963696C 
72656D75 
6A616E20 
73726F67 
206A657A 
65647572 
77207972 
73772065 
00000069'''.splitlines()) 

print(data.decode('iso-8859-2')) 

Sortie:

W chuj bardzo długa nazwa jakiejś zapyziałej pipidówy, brudnej ulicyumer najgorszej rudery we wsi 

Google Translate de polonais à l'anglais:

The dick very long name some zapyziałej Small Town , dirty ulicyumer worst hovel in the village