J'ai un fichier avec des octets de codage little-endian, je veux prendre N
octets, spécifier endianess et les convertir en nombre décimal en utilisant python (n'importe quelle version). Comment le faire correctement?Comment convertir un blob en entier en python?
Répondre
En Python 3 vous pouvez utiliser quelque chose comme ceci:
int.from_bytes(byte_string, byteorder='little')
Ooooo Je ne le savais pas. +1 –
Ok, nous avons une solution pour Python 3. Comment faire pour Python 2? – warchantua
En utilisant 'struct' comme @ juanpa.arrivillaga a mentionné – dunder
En utilisant Python 3 (ou 2), vous pouvez y parvenir avec la bibliothèque struct.
with open('blob.dat', 'rb') as f:
data = f.read(n)
Maintenant, vous déballez en utilisant le format specifier string approprié. Par exemple, big-endian int:
num = struct.unpack(">i",data)
'struct' est également disponible en Python2, n'est-ce pas? – VPfB
@VPfB Oui. Voir les [docs] (https://docs.python.org/2.7/library/struct.html#module-struct). –
Comme le montre la réponse « Harshad Mulmuley, cela est facile en Python 3, en utilisant la méthode int.from_bytes
. En Python 2, c'est un peu plus compliqué. Le module struct
est conçu pour gérer les types de données C standard. Il ne gérera pas les entiers de longueur arbitraire (entiers Python 2 long
), car ils ne sont pas natifs de C. Mais vous pouvez les convertir en utilisant une simple boucle for
. Je m'attends à ce que ce soit sensiblement plus lent que le Python 3, puisque les boucles Python for
sont plus lentes que la boucle à la vitesse C, comme le fait probablement int.from_bytes
.
from binascii import hexlify
def int_from_bytes_LE(s):
total = 0
for c in reversed(s):
total = (total << 8) + ord(c)
return total
# Test
data = (
(b'\x01\x02\x03\x04', 0x04030201),
(b'\x01\x02\x03\x04\x05\x06\x07\x08', 0x0807060504030201),
(b'\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef',
0xefcdab8967452301efcdab8967452301),
)
for s, u in data:
print hexlify(s), u, int_from_bytes_LE(s)
#print(hexlify(s), u, int.from_bytes(s, 'little'))
sortie
01020304 67305985 67305985
0102030405060708 578437695752307201 578437695752307201
abcdefabcdef 318753391026855559389420636404904698625 318753391026855559389420636404904698625
(je mets que Python 3 appel d'impression là-bas de sorte que vous pouvez facilement vérifier que ma fonction donne le même résultat que int.from_bytes
).
Si vos données sont vraiment grand et vous ne voulez pas perdre RAM inverser votre chaîne d'octets vous pouvez le faire de cette façon:
def int_from_bytes_LE(s):
m = 1
total = 0
for c in s:
total += m * ord(c)
m <<= 8
return total
Bien sûr, qui utilise une RAM pour m
, mais il ne sera pas aussi important que la RAM utilisée pour inverser la chaîne d'entrée.
Vous pouvez probablement utiliser le module struct. Quelle est la taille de «N»? –
Copie possible de [Endianness of integers dans Python] (http://stackoverflow.com/questions/1400012/endianness-of-integers-in-python) –
'N' peut être jusqu'à la taille du fichier. – warchantua