bytes - Lectura de enteros desde un archivo binario en Python
string to bytes python (6)
Estoy tratando de leer un archivo BMP en Python. Sé que los primeros dos bytes indican la firma BMP. Los siguientes 4 bytes son el tamaño del archivo. Cuando ejecuto:
fin = open("hi.bmp", "rb")
firm = fin.read(2)
file_size = int(fin.read(4))
Yo obtengo:
ValueError: literal no válido para int () con base 10: ''F # / x13''
Lo que quiero hacer es leer esos cuatro bytes como un entero, pero parece que Python los está leyendo como caracteres y devolviendo una cadena, que no se puede convertir a un número entero. ¿Cómo puedo hacer esto correctamente?
A partir de Python 3.2+, también puedes lograr esto usando el método int nativo from_bytes
:
file_size = int.from_bytes(fin.read(2), byteorder=''big'')
Tenga en cuenta que esta función requiere que especifique si el número está codificado en formato big o little-endian, por lo que deberá determinar el endian-ness para asegurarse de que funciona correctamente.
Cuando lee un archivo binario, se usa un tipo de datos llamado bytes. Esto es un poco como lista o tupla, excepto que solo puede almacenar enteros de 0 a 255.
Tratar:
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]
O:
file_size = list(fin.read(4))
En lugar de:
file_size = int(fin.read(4))
El método de read
devuelve una secuencia de bytes como una cadena. Para convertir de una secuencia de bytes de cadena a datos binarios, use el módulo de struct
integrado: http://docs.python.org/library/struct.html .
import struct
print(struct.unpack(''i'', fin.read(4)))
Tenga en cuenta que unpack
siempre devuelve una tupla, por lo que struct.unpack(''i'', fin.read(4))[0]
proporciona el valor entero que está buscando.
Probablemente deberías usar la cadena de formato ''<i''
(<es un modificador que indica orden de bytes little-endian y tamaño y alineación estándar; el valor predeterminado es usar el orden, el tamaño y la alineación de bytes de la plataforma). De acuerdo con la especificación de formato BMP, los bytes deben estar escritos en orden de bytes Intel / little-endian.
Excepto struct
también puede usar el módulo de array
import array
values = array.array(''l'') # array of long integers
values.read(fin, 1) # read 1 integer
file_size = values[0]
Mientras está leyendo el archivo binario, necesita descomprimirlo en un entero, así que use el módulo de estructura para ese
import struct
fin = open("hi.bmp", "rb")
firm = fin.read(2)
file_size, = struct.unpack("i",fin.read(4))
Un método alternativo que no hace uso de ''struct.unpack ()'' sería usar NumPy :
import numpy as np
f = open("file.bin", "r")
a = np.fromfile(f, dtype=np.uint32)
''dtype'' representa el tipo de datos y puede ser int #, uint #, float #, complex # o un tipo definido por el usuario. Ver numpy.fromfile
.
Personalmente prefiero usar NumPy para trabajar con matriz / matriz de datos, ya que es mucho más rápido que usar listas de Python.