2013-09-10 7 views
0

Je suis confus au sujet de la représentation hexadécimale d'Unicode. J'ai un exemple de fichier avec un seul caractère mathématique de signe intégral. C'est U + 222B Si je cat le fichier ou l'édite en vi, j'obtiens un signe intégral affiché. Un vidage hexadécimal du fichier montre que son contenu hexadécimal est 88e2 0aabConfus au sujet des représentations Unicode

En python, je peux créer un caractère Unicode intégral et imprimer p rendu sur mon terminal et le signe intégral.

>>> p=u'\u222b' 
>>> p 
u'\u222b' 
>>> print p 
∫ 

Ce qui me embrouille est que je peux ouvrir un fichier avec le signe intégral dans, obtenir le symbole intégral mais le contenu hexadécimal est différent.

>>> c=open('mycharfile','r').read() 
>>> c 
'\xe2\x88\xab\n' 
>>> print c 
∫ 

One est un objet Unicode et une est une chaîne simple, mais quelle est la relation entre les deux codes hexagonaux apparemment pour le même personnage? Comment pourrais-je convertir manuellement l'un à l'autre?

+1

'0x222b' = 8747 est le nombre entier du code qui est, en Unicode, associé au signe intégral,' ∫'. Lorsque vous écrivez du texte dans un fichier ou que vous l'envoyez via le réseau, il doit toujours être sérialisé en bits (généralement, les octets (octets) sont les unités préférées ici. la série '0xe2',' 0x88', '0xab' (ou' 0b11100010', '0b10001000',' 0b10101011' en binaire) est l'encodage UTF-8 (http://en.wikipedia.org/wiki/UTF- 8) de '0x222b'. incidemment, les trois principaux «1» du premier octet vous indiquent que ce code est codé sur trois octets: UTF-8 est à la fois de largeur variable et de «synchronisation». – flow

+0

Obligatoire: http://bit.ly/unipain – Daenyth

+0

ce lien mordu semble prometteur. il faut aussi souligner que la gestion Unicode est beaucoup plus saine dans Py3 que dans Py2, au point que ce facteur devrait peser lourd dans la décision de choisir la version Python à utiliser. malheureusement, il y a une division non-bonne et continue entre Py2 et Py3, avec le soutien de la bibliothèque tierce partie en retard. où Py3 brille, c'est que les vieilles 'chaînes ASCII' ont disparu; vous avez toujours affaire à un buffer d'octets (encodé) ou bien un texte (Unicode) (décodé). il s'agit juste de changer de concepts/de nommer des choses, mais alors la programmation est une question de concepts et de noms. – flow

Répondre

3

La chaîne en clair a été codée en utilisant UTF-8, l'une des nombreuses façons de représenter les points de code Unicode en octets. UTF-8 est un encodage multi-octets qui a la caractéristique souvent utile que c'est un sur-ensemble d'ASCII - le même octet encode tout caractère ASCII en UTF-8 ou en ASCII.

En Python 2.x, utilisez la méthode encode sur un objet Unicode pour coder, et decode ou le constructeur unicode à décoder:

>>> u'\u222b'.encode('utf8') 
'\xe2\x88\xab' 
>>> '\xe2\x88\xab'.decode('utf8') 
u'\u222b' 
>>> unicode('\xe2\x88\xab', 'utf8') 
u'\u222b' 

print, lorsqu'il est administré un argument Unicode, code pour implicitement . Sur mon système:

>>> sys.stdout.encoding 
'UTF-8' 

Voir cette réponse pour une discussion plus du comportement de print: Why does Python print unicode characters when the default encoding is ASCII?

Python 3 choses gère un peu différemment; les changements sont documentés ici: http://docs.python.org/3.0/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit

+2

Doit lire: [Le minimum absolu que tout développeur de logiciel doit absolument, positivement doit savoir sur Unicode et jeux de caractères (pas d'excuses!)] (Http://www.joelonsoftware.com/articles/Unicode.html) par Joel Spolsky. – usr2564301

0

D'accord je l'ai. Merci pour les réponses. Je voulais voir comment faire la conversion plutôt que de convertir une chaîne en utilisant Python.

la conversion fonctionne de cette façon.

Si vous avez un caractère Unicode, dans mon exemple un symbole intégral.

décharge Octal produit

echo -n "∫"|od -x 
0000000 88e2 00ab 

Chaque paire hexagonale sont inversés de sorte que cela signifie vraiment

e288ab00 

Le premier caractère hexagonal est E. le bit signifie ceci est une chaîne Unicode et les deux suivantes bits indiquent qu'il est 3 trois octets (16 bits) pour représenter le personnage. Les deux premiers bits des chiffres hexadécimaux restants sont jetés (ils signifient qu'ils sont unicode.) Le flux complet de bits est

111000101000100010101011 

Jeter les 4 premiers bits et les deux premiers bits des chiffres hexadécimaux restants

0010001000101011 

Re exprimant cela en hex

222B 

Ils tu l'as!

+0

"le bit haut signifie qu'il s'agit d'une chaîne Unicode" n'est pas tout à fait correct. Cela brouille la ligne entre l'utilisation de caractères qui n'étaient pas en ASCII et les détails de codage spécifiques à UTF-8. Plus précisément, le bit haut signifie qu'il fait partie d'un codage multi-octets; le nombre de 1 avant le premier 0 vous indique le nombre total d'octets dans le codage (3, dans ce cas). Vous avez le traitement réel correct, mais je recommande de lire attentivement l'essai de Joel sur le logiciel Jongware lié à. Unicode et les codages sont des concepts connexes, mais pas aussi interchangeables que ce libellé l'indique. –