将二进制数据转换为“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='')
使用裸机 except
是 considered 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。
我有一个充满二进制数据的文件,表示以大端顺序排列的 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='')
使用裸机
except
是 considered 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。