2012-10-29 3 views
18

En passant par un peu de code Python, je remarque qu'il y a un certain nombre de représentations différentes pour les valeurs hexadécimales. Par exemple, si je choisis un certain nombre comme ceci:Différence entre différents types hexadécimaux/représentations en Python

xx = '\x03\xff' 

Ensuite, la commande suivante (une version dont je me sers pour convertir peu endian big endian)

yy = hex(struct.unpack('>H', xx)[0]) 

retournera:

'0x3ff' 

Cependant, cette commande

zz = xx.encode('hex') 

retournera:

'03ff' 

Enfin, l'impression juste de la valeur sur renverra cette

'\x03\xff' 

Des regards de celui-ci, il y a trois différents types de hex alors.

  1. '\xFF'
  2. '0xFF'
  3. 'FF'

Quelle est la différence?

points bonus si quelqu'un pourrait suggérer une meilleure façon de convertir un peu endian à un grand nombre de endian. La méthode ci-dessus pour yy ne fonctionnera pas pour les nombres supérieurs à deux octets assez obstinément et je travaille avec certaines chaînes hexadécimales de 16 octets (y compris les valeurs qui ne correspondent pas à une valeur ascii/entier)

+0

Numpy a des routines pour aider à l'ordre des octets, http: // docs.scipy.org/doc/numpy/user/basics.byteswapping.html – tpg2114

+0

À la vôtre. Je vais regarder ça maintenant – stephenfin

Répondre

7

Tout ce qui utilise \x est un code d'échappement de chaîne, qui utilise la notation hexadécimale; Les autres codes d'échappement incluent \n pour les nouvelles lignes, \' pour une citation littérale, etc. Une chaîne python est une séquence d'octets et vous pouvez spécifier des valeurs littérales en dehors de la plage imprimable ASCII en utilisant de tels caractères.Lorsque Python fait écho à une valeur de chaîne retour à vous dans l'interpréteur, ou vous imprimez le résultat d'un appel repr() sur une chaîne, Python utilisera ces évasions pour représenter un octet qui ne peut pas être imprimé en caractères ASCII au lieu:

>>> chr(65) 
'A' 
>>> chr(11) 
'\x0b' 

La fonction hex() renvoie une représentation de chaîne très spécifique, tout comme .encode('hex') à la différence que la première inclut le préfixe 0x. Il existe deux autres méthodes pour produire de telles représentations de chaîne; utilisant les formateurs de chaînes '%x' et '%X', qui utilisent des lettres minuscules ou majuscules pour la représentation.

>>> hex(11) 
'0xb' 
>>> '\x0b'.encode('hex') 
'0b' 
>>> '%x' % (11,) 
'b' 
>>> '%X' % (11,) 
'B' 

Ce sont toutes les représentations de chaîne bien (une série de caractères ASCII), et ont la même relation avec les données d'origine en tant que données str(number) est de nombre entier; vous avez changé le type et êtes plus loin de votre objectif de changer l'ordre des octets.

La modification d'une information binaire de little-end à big-endian nécessite que vous connaissiez la taille de cette information. Si tout ce que vous avez sont des entiers courts, alors vous devez retourner tous les deux octets, mais si vous avez des entiers normaux (longs), alors vous avez 4 octets par valeur et vous devez inverser chaque 4 octets. L'utilisation du module struct est, je pense, une excellente approche car vous devez spécifier le type de valeur. Ce qui suit interpréterait xx comme un grand-boutiste court unsigned int, puis emballez revenir à une représentation binaire comme un petit-boutiste unsigned short int:

>>> import struct 
>>> xx = '\x03\xff' 
>>> struct.pack('<H', *struct.unpack('>H', xx)) 
'\xff\x03' 
2

'\ xFF' représente la chaîne contenant le caractère avec le code ASCII 255.

par exemple: print '\x41' donne 'a' (parce que c'est le caractère de code ASCII 41)

le xx.encode('hex') et hex(struct.unpack('>H', xx)[0]) juste donner un humain Représentation hexadécimale lisible des codes ASCII que contient la chaîne xx. Cela signifie que la chaîne résultante contient un nombre de caractères compris entre a et f ou 0 et 9.

Questions connexes