manipulation - Diferencia entre diferentes tipos/representaciones de hex en Python
uuid generator (2)
Mientras avanzo algunos códigos Python, me doy cuenta de que hay varias representaciones diferentes para los valores hexadecimales. Por ejemplo, si elijo un número como este:
xx = ''/x03/xff''
Luego el siguiente comando (una versión del cual estoy usando para convertir little endian a big endian)
yy = hex(struct.unpack(''>H'', xx)[0])
volverá:
''0x3ff''
Sin embargo, este comando
zz = xx.encode(''hex'')
volverá:
''03ff''
Finalmente, imprimiendo solo el valor hacia fuera devolverá este
''/x03/xff''
Por lo que parece hay tres tipos diferentes de hexágonos.
-
''/xFF''
-
''0xFF''
-
''FF''
¿Cual es la diferencia?
Puntos de bonificación si alguien pudiera sugerir una mejor manera de convertir un pequeño endian a un gran número endian. El método anterior para yy
no funcionará para números mayores a dos bytes lo suficientemente obstinadamente y estoy trabajando con algunas cadenas hexadecimales que tienen 16 bytes de longitud (incluidos los valores que no corresponden a un valor ascii / entero)
''/ xFF'' representa la cadena que contiene el carácter con el código ASCII 255.
Por ejemplo: print ''/x41''
da ''A'' (porque este es el carácter con el código ASCII 41)
el xx.encode(''hex'')
y el hex(struct.unpack(''>H'', xx)[0])
simplemente dan una representación hexadecimal legible por humanos de los códigos ASCII que contiene la cadena xx. Esto significa que la cadena resultante contiene una serie de caracteres entre a y f o 0 y 9.
Cualquier cosa que use /x
es un código de escape de cadena, que utiliza la notación hexadecimal; otros códigos de escape incluyen /n
para nuevas líneas, /'
para una cita literal, etc. Una cadena de python es una secuencia de bytes y puede especificar valores literales fuera del rango imprimible de ASCII utilizando dichos caracteres. Cuando Python le devuelve un valor de cadena a usted en el intérprete, o imprime el resultado de una llamada repr()
en una cadena, Python usará dichos escapes para representar cualquier byte que no pueda imprimirse como un carácter ASCII en su lugar:
>>> chr(65)
''A''
>>> chr(11)
''/x0b''
La función hex()
devuelve una representación de cadena muy específica, al igual que .encode(''hex'')
con la diferencia de que la primera incluye el prefijo 0x
. Hay dos métodos más para producir tales representaciones de cadena; usando los formateadores de cadena ''%x''
y ''%X''
, que usan letras minúsculas o mayúsculas para la representación.
>>> hex(11)
''0xb''
>>> ''/x0b''.encode(''hex'')
''0b''
>>> ''%x'' % (11,)
''b''
>>> ''%X'' % (11,)
''B''
Sin embargo, todas estas son representaciones de cadenas (una serie de caracteres ASCII), y tienen la misma relación con los datos originales, ya que str(number)
es con datos enteros; ha cambiado el tipo y está más lejos de su objetivo de cambiar el orden de los bytes.
Cambiar una información binaria de little-ending a big-endian requiere que sepas el tamaño de esa información. Si todo lo que tiene son enteros cortos, entonces necesita voltear cada dos bytes, pero si tiene enteros normales (largos), entonces tiene 4 bytes por valor y necesita revertir cada 4 bytes.
El uso del módulo de struct
es, creo, un enfoque excelente porque debe especificar el tipo de valor. Lo siguiente interpretaría xx
como un int corto sin signo big-endian, luego lo volvería a empaquetar en una representación binaria como un int corto sin signo little-endian:
>>> import struct
>>> xx = ''/x03/xff''
>>> struct.pack(''<H'', *struct.unpack(''>H'', xx))
''/xff/x03''