从二进制文件中读取字符串

3

我想从文件中读取1、2和3字节的数据。 我知道它对应于Linux二进制文件头中的字符串(在这种情况下是ELF)。

根据我在网上找到的示例,我得出了以下代码:

with open('hello', 'rb') as f:
    f.seek(1)
    bytes = f.read(3)
    string = struct.unpack('s', bytes)
    print st

查看struct的官方文档,似乎将s作为参数传递可以让我读取一个字符串。

但我遇到了错误:

st = struct.unpack('s', bytes)
struct.error: unpack requires a string argument of length 1

编辑:使用Python 2.7版本


1
请指定您正在使用的Python版本。在Python 2中,“str”和“bytes”是别名。在Python 3中,file.read() 尝试使用UTF-8编码将字节转换为Unicode。 - Grapsus
@Grapsus:这是错误的。如果文件以二进制模式“b”(OP使用“rb”,即二进制)打开,则f.read()在Python 2和3中都返回bytes。在文本模式下打开时,open使用locale.getpreferredencoding(False)编码,这在Python 3中有时可能是utf-8。 - jfs
请勿使用“bytes”名称。它会遮蔽内置函数。 - jfs
2个回答

4
在您的特殊情况下,只需检查即可。
if bytes == 'ELF':

为了在一步中测试三个字节,使它们分别是字符 ELF

但是如果你想检查数值,就不需要在这里解包任何东西。只需使用 ord(bytes[i])(其中 i 的取值为 0、1、2)获取这三个字节的值即可。

或者你可以使用

byte_values = struct.unpack('bbb', bytes)

要获取三个字节的元组。如果这些字节具有可命名的语义,也可以即时解压缩该元组,如下所示:

width, height, depth = struct.unpack('bbb', bytes)

如果您的字节值应该是无符号的,那么请使用'BBB'而不是'bbb'


实际上,你的 bytes 已经是你要找的字符串了,也就是说,你可以直接测试 if bytes == 'ELF': …。有时候事情就是这么简单;-) - Alfe
1
为什么f.read(3) == b'ELF'是一条注释,应该放在答案顶部? - jfs
如果你需要整数而不是字节串,你可以使用bytearray(bytestring)或者a = array.array('B'); a.fromfile(file, 3)。如果要从二进制文件中读取结构化数据,可以使用struct.Struct.unpack_from(buf)或者file.readinto(ctypes_structure)或者(ctypes_structure * N).from_buffer(mmap_file) - jfs
在我发表评论的时候,只有一个附加问题在评论中提到了常量 'ELF' - Alfe

3
在Python 2中,read返回一个字符串,即“字节串”。要获取单个字节,请使用bytes[i],它将返回另一个字符串,但只包含一个字节。如果需要字节的数值,请使用ordord(bytes[i])。最后,要获取所有字节的数值,请使用map(ord, bytes)
In [4]: s = "foo"

In [5]: s[0]
Out[5]: 'f'

In [6]: ord(s[0])
Out[6]: 102

In [7]: map(ord, s)
Out[7]: [102, 111, 111]

我对Python2.7中read函数的返回类型有些困惑。我以二进制模式打开了一个文件,并读取了一个字节,比如byte = f.read(1)。当我执行print type(byte)时,它显示为str。"字节串"和普通字符串是否不同?在Python中,哪种数据类型可以映射到"字节串"? - Vivek Maran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接