web-dev-qa-db-fra.com

Lire des entiers à partir d'un fichier binaire en Python

J'essaie de lire un fichier BMP en Python. Je connais les deux premiers octets Indique la société BMP. Les 4 octets suivants correspondent à la taille du fichier. Quand j'exécute:

fin = open("hi.bmp", "rb")
firm = fin.read(2)  
file_size = int(fin.read(4))  

Je reçois:

ValueError: Littéral invalide pour int () avec base 10: 'F #\x13'

Ce que je veux faire, c'est lire ces quatre octets sous forme d'entier, mais il semble que Python les lit sous forme de caractères et renvoie une chaîne, qui ne peut pas être convertie en entier. Comment puis-je faire cela correctement? 

67
Manuel Aráoz

La méthode read renvoie une séquence d'octets sous forme de chaîne. Pour convertir une séquence d'octets de chaîne en données binaires, utilisez le module intégré struct: http://docs.python.org/library/struct.html

import struct

print(struct.unpack('i', fin.read(4)))

Notez que unpack renvoie toujours un tuple, donc struct.unpack('i', fin.read(4))[0] donne la valeur entière que vous recherchez.

Vous devriez probablement utiliser la chaîne de formatage '<i' (<est un modificateur qui indique l'ordre des octets et la taille et l'alignement standard de little-endian - la valeur par défaut consiste à utiliser l'ordre, la taille et l'alignement des octets de la plateforme). Selon la spécification de format BMP, les octets doivent être écrits dans l'ordre des octets Intel/little-endian.

105
codeape

Une autre méthode qui n’utilise pas 'struct.unpack ()' serait d’utiliser NumPy :

import numpy as np

f = open("file.bin", "r")
a = np.fromfile(f, dtype=np.uint32)

'dtype' représente le type de données et peut être int #, uint #, float #, complexe # ou un type défini par l'utilisateur. Voir numpy.fromfile .

Personnellement, préférez utiliser NumPy pour travailler avec des données de tableaux/matrices car il est beaucoup plus rapide que d’utiliser des listes Python.

38
Emanuel Ey

A partir de Python 3.2+, vous pouvez également accomplir cela en utilisant la méthode from_bytes native int:

file_size = int.from_bytes(fin.read(2), byteorder='big')

Notez que cette fonction nécessite que vous spécifiiez si le nombre est codé au format big-endian ou little-endian. Vous devrez donc déterminer la finalité pour vous assurer qu'il fonctionne correctement.

8
CrepeGoat

Sauf que struct, vous pouvez également utiliser le module array

import array
values = array.array('l') # array of long integers
values.read(fin, 1) # read 1 integer
file_size  = values[0]
6
Nick Dandoulakis

Lorsque vous lisez le fichier binaire, vous devez le décompresser en un entier, utilisez donc struct module pour cela.

import struct
fin = open("hi.bmp", "rb")
firm = fin.read(2)  
file_size, = struct.unpack("i",fin.read(4))
4
Anurag Uniyal

Lorsque vous lisez un fichier binaire, un type de données appelé octets est utilisé. C'est un peu comme liste ou Tuple, sauf qu'il ne peut stocker que des entiers de 0 à 255.

Essayer:

file_size = fin.read(4)
file_size0 = file_size[0]
file_size1 = file_size[1]
file_size2 = file_size[2]
file_size3 = file_size[3]

Ou:

file_size = list(fin.read(4))

Au lieu de:

file_size = int(fin.read(4))
0
Super S