在Python中获取文件的原始二进制表示

5

我希望使用Python 3将文件中的确切比特序列转换为字符串。有几个关于这个主题的问题接近答案,但并没有完全回答。到目前为止,我有以下代码:

>>> data = open('file.bin', 'rb').read()
>>> data
'\xa1\xa7\xda4\x86G\xa0!e\xab7M\xce\xd4\xf9\x0e\x99\xce\xe94Y3\x1d\xb7\xa3d\xf9\x92\xd9\xa8\xca\x05\x0f$\xb3\xcd*\xbfT\xbb\x8d\x801\xfanX\x1e\xb4^\xa7l\xe3=\xaf\x89\x86\xaf\x0e8\xeeL\xcd|*5\xf16\xe4\xf6a\xf5\xc4\xf5\xb0\xfc;\xf3\xb5\xb3/\x9a5\xee+\xc5^\xf5\xfe\xaf]\xf7.X\x81\xf3\x14\xe9\x9fK\xf6d\xefK\x8e\xff\x00\x9a>\xe7\xea\xc8\x1b\xc1\x8c\xff\x00D>\xb8\xff\x00\x9c9...'

>>> bin(data[:][0])
'0b11111111'

好的,我可以翻译关于IT技术方面的内容。我能够理解二进制数,但是我不明白为什么要使用data[:][x],而且输出结果前面有0b。同时,好像我需要循环整个字符串并进行一些转换和解析才能得到正确的输出结果。是否有更简单的方法来获取01序列,而无需循环、解析和连接字符串?

提前感谢!


3
在二进制模式下打开文件并读取,会产生字节对象而不是字符串对象。你确定你正在使用 Python 3 吗? - SilentGhost
是的,我确定我正在使用py3k。它们可能是字节对象,但终端用单引号显示它们。 - maximus
1
单引号或双引号并不重要,但字节对象的表示以b开头。就像这样 b'\xa1\xa7\xda4\x86G...',你在上面漏掉了。 - Lennart Regebro
啊,我明白了。我一定是复制/粘贴错了。哎呀。 - maximus
4个回答

6

我首先会预计算所有0..255值的字符串表示

bytetable = [("00000000"+bin(x)[2:])[-8:] for x in range(256)]

或者,如果您更喜欢LSB顺序的位
bytetable = [("00000000"+bin(x)[2:])[-1:-9:-1] for x in range(256)]

然后可以通过以下方式获得二进制格式的整个文件

binrep = "".join(bytetable[x] for x in open("file", "rb").read())

2
不错的解决方案,但有一些注释:1. Python 3没有xrange()(这是一个Python 3问题)。2.您以某种“大端”顺序排列位,这对我来说非常不自然。至少应该指出。3.通常认为,具有与内置类(bytes)相同名称的变量是错误的。 - Sven Marnach
现在我更喜欢它了,+1 :) - Sven Marnach
谢谢回复,但是...我遇到了一个错误:TypeError: ord()需要长度为1的字符串,但是却得到了整数 - maximus
1
另外一个要注意的点是,ord(x) 不能用于字节对象(例如以二进制模式读取的文件)。遍历字节会产生一系列整数,因此请将 [ord(x)] 替换为 [x] - Thomas K
@Thomas K:谢谢,已修复并且花时间进行了测试。 - 6502

3

如果您可以使用外部模块,可以使用bitstring

>>> import bitstring
>>> bitstring.BitArray(filename='file.bin').bin
'110000101010000111000010101001111100...'

就是这样。它只是将整个文件的二进制字符串表示。


注意,使用Python 3.6.4时,输出结果不包含“0b”,因此您需要去掉前两位。 - Alekos

2

目前还不太清楚这个比特序列的意思。我认为从第0字节的第0位开始最自然,但实际上取决于你想要什么。

下面是一些代码,用于访问从第0字节的第0位开始的比特序列:

def bits_from_char(c):
    i = ord(c)
    for dummy in range(8):
        yield i & 1
        i >>= 1

def bits_from_data(data):
    for c in data:
        for bit in bits_from_char(c):
            yield bit

for bit in bits_from_data(data):
    #  process bit

(另外一点需要注意的是,在代码中您不需要使用 data[:][0]。只需使用 data[0] 即可,但不需要先复制整个字符串。)

1
为了在Python 3中将原始二进制数据(例如b'\xa1\xa7\xda4\x86')转换为表示数据的比特串,以二进制系统(基数为2)中的数字形式呈现,可以使用以下方法:
>>> data = open('file.bin', 'rb').read()
>>> bin(int.from_bytes(data, 'big'))[2:]
'1010000110100111110110100011010010000110...'

请查看将二进制转换为ASCII码或反之亦然


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