Чтение целых чисел из двоичного файла в Python - PullRequest
68 голосов
/ 22 июля 2009

Я пытаюсь прочитать файл BMP в Python. Я знаю первые два байта указать фирму BMP. Следующие 4 байта - это размер файла. Когда я выполню:

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

Я получаю:

ValueError: недопустимый литерал для int () с основанием 10: 'F # \ x13'

Что я хочу сделать, так это прочитать эти четыре байта как целое число, но кажется, что Python читает их как символы и возвращает строку, которую нельзя преобразовать в целое число. Как я могу сделать это правильно?

Ответы [ 6 ]

106 голосов
/ 22 июля 2009

Метод read возвращает последовательность байтов в виде строки. Чтобы преобразовать строковую последовательность байтов в двоичные данные, используйте встроенный модуль struct: http://docs.python.org/library/struct.html.

import struct

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

Обратите внимание, что unpack всегда возвращает кортеж, поэтому struct.unpack('i', fin.read(4))[0] дает целочисленное значение, которое вы ищете.

Вероятно, вам следует использовать строку формата '<i' (<- это модификатор, который указывает порядок байтов в младшем порядке, а также стандартный размер и выравнивание - по умолчанию используется порядок, размер и выравнивание байтов платформы). В соответствии со спецификацией формата BMP байты должны быть записаны в порядке байтов Intel / little-endian. </p>

39 голосов
/ 30 июля 2012

Альтернативный метод, который не использует struct.unpack (), будет использовать NumPy :

import numpy as np

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

'dtype' представляет тип данных и может быть int #, uint #, float #, complex # или пользовательским типом. См. numpy.fromfile.

Лично предпочитаю использовать NumPy для работы с данными массива / матрицы, поскольку это намного быстрее, чем использование списков Python.

8 голосов
/ 09 мая 2017

Начиная с Python 3.2+, вы также можете сделать это, используя from_bytes native int метод:

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

Обратите внимание, что эта функция требует, чтобы вы указали, кодируется ли число в формате с прямым или прямым порядком байтов, поэтому вам придется определить порядок байтов, чтобы убедиться, что он работает правильно.

6 голосов
/ 22 июля 2009

Кроме struct вы также можете использовать array модуль

import array
values = array.array('l') # array of long integers
values.read(fin, 1) # read 1 integer
file_size  = values[0]
4 голосов
/ 22 июля 2009

Когда вы читаете двоичный файл, вам нужно распаковать его в целое число, поэтому используйте для этого структурный модуль

import struct
fin = open("hi.bmp", "rb")
firm = fin.read(2)  
file_size, = struct.unpack("i",fin.read(4))
0 голосов
/ 11 апреля 2018

Когда вы читаете из двоичного файла, используется тип данных, называемый байтами.Это немного похоже на список или кортеж, за исключением того, что оно может хранить только целые числа от 0 до 255.

Попробуйте:

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]

Или:

file_size = list(fin.read(4))

Вместо:

file_size = int(fin.read(4))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...