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

时间:2015-10-05 00:55:46

标签: python string encoding binary

我有一个文件填充了二进制数据,表示大端序排列的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 char时打印出十六进制表示。

虽然我从哪里出发?我需要将b'a'转换为'1100001',因为我实际上关心的是比特,而不是字节。

2 个答案:

答案 0 :(得分:4)

您可以将b'a'转换为相应的整数ord值,然后使用'{:b}'.format以二进制格式打印int:

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='')

答案 1 :(得分:2)

在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的所有说明,您可以使用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