【问题标题】:Reading integers from binary file in Python在 Python 中从二进制文件中读取整数
【发布时间】:2010-11-12 21:40:49
【问题描述】:

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

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

我明白了:

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

我想要做的是将这四个字节作为整数读取,但似乎 Python 正在将它们作为字符读取并返回一个字符串,该字符串无法转换为整数。我怎样才能正确地做到这一点?

【问题讨论】:

  • 如果您的目标是使用位图,而不是花时间编写自己的 BMP 库(不是那听起来不好玩...),您可以使用 PIL pythonware.com/products/pil 你可能已经安装了。试试:导入图片
  • 感谢 Jared,但我想手动阅读 bmp 只是为了好玩! :)

标签: python file binary integer


【解决方案1】:

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'

【讨论】:

  • 我经常写i = struct.unpack(...)[0]而不是i, = struct.unpack(...)
  • @Otto 你有什么理由更喜欢其中一种方式吗?有什么逻辑上的区别吗?
  • 我很惊讶没有内置函数可以从 Python 文件中读取整数(或 Shorts 等)。我不是 Java 专家,但我相信它具有诸如 readUnsignedShort() 之类的本机函数来执行此操作。
  • @codeape 你能否定义一下 [0] 正在做什么,或者至少它是什么类型的语言元素。它不是很明显,而且几乎不可能在 Python 文档中搜索。
  • 对于列表和元组,obj[N]表示:获取obj的第N个元素。见docs.python.org/tutorial/introduction.html#lists
【解决方案2】:

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

【讨论】:

  • 文件打开可以跳过:a = np.fromfile('file.bin', dtype=np.uint32)
  • 就我而言,这并没有直接起作用。根据您的编码,您可以尝试更深奥的 dtype,例如:np.fromfile( file, dtype='>i2')、> 或
【解决方案3】:

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

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

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

【讨论】:

  • 在 python3 中,int 是动态调整大小的(它与 Python2 的 long 实现相同;这有时也称为“大整数”),我相信这是首先添加这个int 方法。 docs.python.org/3/library/….
  • 那么为什么是 2?你怎么知道的?
  • 哦,数字 2 来自 OP;这不是一个神奇的数字或任何东西。这可以通过用一些正整数变量 n 替换 2 来概括,它的工作原理都是一样的
【解决方案4】:

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

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

【讨论】:

  • 好点。但是这个方案没有struct模块灵活,因为所有通过values.read()读取的元素都必须是长整数(不方便先读取一个长整数,一个字节,再读取一个长整数,用数组模块)。
  • 我同意。 array 是一种读取二进制文件的有效方法,但在我们必须处理结构时不是很灵活,正如您正确提到的那样。
  • array.read 自 1.51 起已弃用,取而代之的是 array.fromfile
【解决方案5】:

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

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

【讨论】:

  • struct.unpack 返回一个元组
【解决方案6】:

当您从二进制文件中读取数据时,会使用一种称为字节的数据类型。这有点像列表或元组,只是它只能存储 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))

【讨论】:

    【解决方案7】:

    这是一个较晚的解决方案,但我认为它可能会有所帮助。

    fin = open("hi.bmp", "rb")
    firm = fin.read(2)
    file_size = 0
    for _ in range(4):  
        (file_size << 8) += ord(fin.read(1))
    

    【讨论】:

      猜你喜欢
      • 2016-11-13
      • 1970-01-01
      • 2011-12-26
      • 2011-09-02
      • 2015-11-11
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多