将二进制数据转换为“0”和“1”的文字串

Turning binary data into a literal string of '0's and '1's

我有一个充满二进制数据的文件,表示以大端顺序排列的 2 字节指令序列。

我需要能够将这些指令解码为更有意义的等价物,但我无法将数据转换为我可以使用的格式。

我认为最好将指令转换为实际的 0 和 1 字符串。

到目前为止,我已经写了这个:

 def slurpInstructions(filename):
  instructions = []
  with open(filename, 'rb') as f:
    while True:
      try:
        chunk = f.read(1)
        print(struct.unpack('c', chunk))
      except: 
        break

一次打印出字节 1,如下所示:

(b'\x00',)
(b'a',)

我知道文件中的第一条指令是:

0000000001100001

因此,看起来它正在打印出与每个字节的整数值相对应的 ascii 字符,除了当没有 int 值的 ascii 字符时它只是打印出十六进制表示。

我从这里去哪里?我需要将我的 b'a' 变成 '1100001' 因为我实际上关心的是位,而不是字节。

您可以将 b'a' 转换为相应的整数 ord value, and then print the int in binary format using '{:b}'.format:

In [6]: '{:b}'.format(ord(b'a'))
Out[6]: '1100001'

  • 一次读取一个字节的大文件可能会非常慢。通过每次调用 f.read 读取更多字节,您将获得更好的性能。 您可以使用 1024 字节的块迭代文件的内容:

    with open(filename, 'rb') as f:
        for chunk in iter(lambda: f.read(1024), b''):
    
  • 同样,为每个字节调用一次 print 可能会非常慢。通过每次调用 print 打印更多字节,您将获得更好的性能。因此,您可以使用列表理解来遍历 chunk 中的字节,将每个字节转换为其字符串二进制格式,然后使用 ''.join 将字符串连接在一起:

    print(''.join(['{:b}'.format(ord(c)) for c in chunk]), end='')
    
  • 使用裸机 exceptconsidered a bad practice。如果您选择在此处使用 try..except,请仅列出您希望处理的异常:

    try:
        ...
    except IOError:          
    

def slurpInstructions(filename):
    with open(filename, 'rb') as f:
        for chunk in iter(lambda: f.read(1024), b''):
            print(''.join(['{:b}'.format(c) for c in chunk]), end='')

在Python 3、将2个字节转换成位串('{:b}'.format() may be slightly slower):

>>> bin(int.from_bytes(b'\x00a', 'big'))[2:].zfill(16)
'0000000001100001'

对于单一来源 Python 2/3 兼容版本,请参阅 Convert binary to ASCII and vice versa

加载所有指令 time- and space-efficiently, you could use array module:

#!/usr/bin/env python
import os
import sys
from array import array

instructions = array('H') # each instruction is >=2 bytes   
n = os.path.getsize(filename) // instructions.itemsize # number of instructions
with open(filename, 'rb') as file:
    instructions.fromfile(file, n) # slurp file
if sys.byteorder == 'little':
    instructions.byteswap() # force big-endian order

for h in instructions: # print as bitstrings
    print('{:016b}'.format(h))

有关有效读取二进制文件的其他方法,请参阅 Reading binary file in Python and looping over each byte