2009-05-15 5 views
13

Je souhaite convertir un nombre de points de code Unicode lus à partir d'un fichier en leur codage UTF8. Par exemple, je souhaite convertir la chaîne 'FD9B' en 'EFB69B'.Convertir un codepoint unicode en hexadécimal UTF8 en python

je peux le faire manuellement à l'aide des chaînes littérales comme ceci:

u'\uFD9B'.encode('utf-8') 

, mais je ne peux pas travailler sur la façon de le faire programatically.

Répondre

18

Utilisez la fonction intégrée unichr() pour convertir le nombre de caractères, puis coder que:

>>> unichr(int('fd9b', 16)).encode('utf-8') 
'\xef\xb6\x9b' 

C'est la chaîne elle-même. Si vous voulez que la chaîne soit hexadécimale ASCII, vous devez parcourir et convertir chaque caractère c en hexadécimal, en utilisant hex(ord(c)) ou similaire.

+4

La sortie n'est pas comme spécifié par la question. Quoi qu'il en soit, si l'OP est heureux ... – tzot

+3

FYI pour Py3K c'est 'chr (int ('fd9b', 16)). Encoder ('utf-8')'. –

+0

@tzot: ''' .join ('{: 02X}'. Format (n) pour n dans chr (int ('FD9B', 16)). Encoder())' donne la chaîne '' EFB69B'' dans Python 3. – CoDEmanX

2
Python 2.6.2 (r262:71600, Apr 16 2009, 09:17:39) 
[GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> u'\uFD9B'.encode('utf-8') 
'\xef\xb6\x9b' 
>>> s = 'FD9B' 
>>> i = int(s, 16) 
>>> i 
64923 
>>> unichr(i) 
u'\ufd9b' 
>>> _.encode('utf-8') 
'\xef\xb6\x9b' 
3
data_from_file='\uFD9B' 
unicode(data_from_file,"unicode_escape").encode("utf8") 
1

Si la longueur de la chaîne d'entrée est un multiple de 4 (à savoir vos points de code unicode sont codées en UCS-2), essayez ceci:

import struct 

def unihex2utf8hex(arg): 
    count= len(arg)//4 
    uniarr= struct.unpack('!%dH' % count, arg.decode('hex')) 
    return u''.join(map(unichr, uniarr)).encode('utf-8').encode('hex') 

>>> unihex2utf8hex('fd9b') 
'efb69b' 
3

est ici une solution complète:

>>> ''.join(['{0:x}'.format(ord(x)) for x in unichr(int('FD9B', 16)).encode('utf-8')]).upper() 
'EFB69B' 
0

Parce que vous pouvez rencontrer une erreur lors de l'utilisation unichr avec de larges caractères unicode:

>>> n = int('0001f600', 16) 
>>> unichr(n) 
ValueError: unichr() arg not in range(0x10000) (narrow Python build) 

Voici une autre approche pour une large unicode sur python étroit construit:

>>> n = int('0001f600', 16) 
>>> s = '\\U{:0>8X}'.format(n) 
>>> s = s.decode('unicode-escape') 
>>> s.encode("utf-8") 
'\xf0\x9f\x98\x80' 

Et en utilisant la valeur de la question initiale:

>>> n = int('FD9B', 16) 
>>> s = '\\u{:0>4X}'.format(n) 
>>> s = s.decode('unicode-escape') 
>>> s.encode("utf-8") 
'\xef\xb6\x9b' 
Questions connexes