用Python读取和解释二进制文件中的数据

25

我想逐字节读取一个文件,并检查每个字节的最后一位是否被设置:

#!/usr/bin/python

def main():
    fh = open('/tmp/test.txt', 'rb')
    try:
        byte = fh.read(1)
        while byte != "":
            if (int(byte,16) & 0x01) is 0x01:
                print 1
            else:
                print 0
            byte = fh.read(1)
    finally:
        fh.close

    fh.close()

if __name__ == "__main__":
        main()

我得到的错误是:

Traceback (most recent call last):
  File "./mini_01.py", line 21, in <module>
    main()
  File "./mini_01.py", line 10, in main
    if (int(byte,16) & 0x01) is 0x01:
ValueError: invalid literal for int() with base 16: '\xaf'

有什么想法吗?我试过使用 struct 和 binascii 模块,但没有成功。


2
在你开始处理这个问题之前,请阅读https://dev59.com/DHVC5IYBdhLWcg3wZwTj,并打开*那个*问题的副本;) - user395760
3个回答

56

尝试使用bytearray类型(Python 2.6及更高版本),它更适合处理字节数据。你的try块将变为:

ba = bytearray(fh.read())
for byte in ba:
    print byte & 1

或者创建一个结果列表:

low_bit_list = [byte & 1 for byte in bytearray(fh.read())]
这有效是因为当你索引一个bytearray时,你会得到一个整数(0-255),而如果你只从文件中读取一个字节,则会得到一个单个字符的字符串,因此需要使用ord将其转换为整数。
如果您的文件太大,无法轻松地保存在内存中(虽然我猜它不是),则可以使用mmap从缓冲区创建bytearray
import mmap
m = mmap.mmap(fh.fileno(), 0, access=mmap.ACCESS_READ)
ba = bytearray(m)

6
感谢提供大文件解决方案,它让我免去了很多烦恼。您真是一位绅士和学者。 - brichins

9

您需要使用ord而不是int

if (ord(byte) & 0x01) == 0x01:

6
你真的应该使用 == 来比较整数,而不是通过它们的标识来进行比较! - Scott Griffiths
好的点子。我想过了,但当我粘贴那个时没有改变它...已经修复。 - nmichaels

5

一种方式:

import array

filebytes= array.array('B')
filebytes.fromfile(open("/tmp/test.txt", "rb"))
if all(i & 1 for i in filebytes):
    # all file bytes are odd

另一种方法:
fobj= open("/tmp/test.txt", "rb")

try:
    import functools
except ImportError:
    bytereader= lambda: fobj.read(1)
else:
    bytereader= functools.partial(fobj.read, 1)

if all(ord(byte) & 1 for byte in iter(bytereader, '')):
    # all bytes are odd
fobj.close()

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