在Python中从二进制文件读取整数


82

我正在尝试在Python中读取BMP文件。我知道前两个字节表示BMP公司。接下来的4个字节是文件大小。当我执行时:

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

我得到:

ValueError:以10为底的int()的无效文字:'F#\ x13'

我想做的是将这四个字节读取为整数,但是Python似乎将它们读取为字符并返回一个字符串,该字符串无法转换为整数。如何正确执行此操作?


2
如果您的目标是使用位图而不是花时间编写自己的BMP库(不是听起来很有趣...),则可以使用可能已经安装的PIL pythonware.com/products/pil。试试:汇入图片
Jared Updike

7
谢谢Jared,但我想手动阅读bmp只是为了获得乐趣!:)
Manuel Araoz

Answers:


123

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字节顺序写入。


22
i = struct.unpack(...)[0]我经常写而不是写i, = struct.unpack(...)
Otto Allmendinger

@Otto有什么理由让您更喜欢一种方式吗?有逻辑上的区别吗?
卡托

2
我发现非常令人惊讶的是,没有内置函数可以从Python文件中读取整数(或Shorts等)。我不是Java专家,但我相信它具有诸如readUnsignedShort()之类的本机函数来执行此操作。
卡托

@codeape您能否定义[0]在做什么,或者至少是什么类型的语言元素。这不是立即显而易见的,并且几乎不可能在Python文档中进行搜索。
卡托

对于列表和元组,obj [N]表示:获取obj的第N个元素。参见docs.python.org/tutorial/introduction.html#lists
codeape 2012年

50

不使用'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列表要快得多。


13
可以跳过文件打开:a = np.fromfile('file.bin', dtype=np.uint32)
Mathieu Schopfer

16

从Python 3.2+开始,您还可以使用本from_bytes机int方法完成此操作:

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

请注意,此功能要求您指定数字是以大尾数格式还是小尾数格式编码的,因此您必须确定尾数以确保其正确工作。


6

除了struct你也可以使用array模块

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

好点子。但是此解决方案不如struct模块灵活,因为所有读取value.read()的元素都必须是长整数(使用阵列模块)。
Eric O Lebigot 09年

我同意。array正如您正确提到的那样,它是一种读取二进制文件的有效方法,但是当我们必须处理结构时,它不是非常灵活。
Nick Dandoulakis 09年

1
从1.51开始不推荐使用array.read,而支持array.fromfile

4

在读取二进制文件时,需要将其解压缩为整数,因此请使用struct模块

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

struct.unpack返回一个元组
luc

1

从二进制文件读取时,将使用称为字节的数据类型。这有点像列表或元组,只不过它只能存储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))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.