在python中,如何将二进制数据从文件转换为可读的二进制数据?

在python中,如何将二进制数据从文件转换为可读的二进制数据?,python,python-3.x,binary,hex,bits,Python,Python 3.x,Binary,Hex,Bits,在我所在的班级里,我们被分配到一个简单的mips模拟器。我的程序应该处理的指令以二进制文件的形式给出。我不知道如何从那个文件中得到有用的东西。这是我的密码: import struct import argparse '''open a parser to get command line arguments ''' parser = argparse.ArgumentParser(description='Mips instruction simulator') '''add two re

在我所在的班级里,我们被分配到一个简单的mips模拟器。我的程序应该处理的指令以二进制文件的形式给出。我不知道如何从那个文件中得到有用的东西。这是我的密码:

import struct
import argparse

'''open a parser to get command line arguments '''
parser = argparse.ArgumentParser(description='Mips instruction simulator')

'''add two required arguments for the input file and the output file'''
parser.add_argument('-i', action="store", dest='infile_name', help="-i INPUT_FILE", required=True)
parser.add_argument('-o', action="store", dest='outfile_name', help="-o OUTPUT_FILE_NAME", required=True)

'''get the passed arguments'''
args = parser.parse_args()


class Disassembler:
    '''Disassembler for mips code'''
    instruction_buffer = None
    instructions_read = 0

    def __init__(self, filename):
        bin_file = None
        try:
            bin_file = open(filename, 'rb')
        except:
            print("Input file: ", filename, " could not be opened. Check the name, permissions, or path")
            quit()

        while True:
            read_bytes = bin_file.read(4)
            if (read_bytes == b''):
                break
            int_var = struct.unpack('>I', read_bytes)
            print(int_var)

        bin_file.close()


disembler = Disassembler(args.infile_name)
所以,首先我只是打印我读取的4个字节,看看返回了什么。 我希望看到普通的位(只有1和0)。我得到的是我读到的字节字符串。所以我试着在谷歌上搜索,看看我能做些什么。所以我发现我可以使用struct将这些字节字符串转换成整数。以类似(4294967295,)的格式输出它们

这仍然是令人讨厌的,因为我必须修剪它,使之成为一个可用的整数,然后我仍然必须将它转换为位(基数2)。很好,我可以用struct读取有符号或无符号的字节,因为输入文件的输入有一半是有符号的32位数字

所有这些看起来都比从二进制文件中获取位要复杂得多。有没有更简单的方法?另外,您是否可以像向不太熟悉深奥的python代码并且不熟悉二进制数据的人那样解释它

我的总体目标是从我读取的每4个字节中直接取出32位。文件的开头是mips操作码列表。所以我需要能够看到这些数字的特定部分,比如前5位,然后是下6位,等等。文件结尾包含32位带符号整数值。文件的两部分由一个中断操作码分隔


谢谢你能给我的任何帮助。我无法通过搜索找到任何直接的答案,这让我发疯。如果您想查看二进制文件,请告诉我在哪里,我会发布它。

这样您可以访问文件中的每个位

"".join(format(i, "08b") for i in byte_string)
例如:

>>> "".join(format(i, "08b") for i in b"\x23\x54a")
'001000110101010001100001'

请记住,普通Python整数没有固定的位宽度:它们的大小与需要的大小一样。当您想要将有符号整数转换为位字符串时,这可能会很烦人。我建议您坚持目前的做法:使用

n = struct.unpack('>I', read_bytes)[0]
然后使用
格式(n,'032b')
'{0:032b}'。格式(n)
将其转换为位字符串,如果要打印位

要访问或修改整数中的位,您不应该为字符串转换而烦恼,而是应该使用Python的逐位运算符,
&
|
^
~
。例如,
(n>>7)&1
为您提供
n
的第7位


有关这些运算符的详细信息,请参见Python文档中的和以下部分。

您是只想对值的位进行转换,还是希望将其转换为形式以供进一步操作?我需要将其作为位进行阅读。因为我需要每个32位值的特定长度。就像我需要知道前6位是什么,然后是下5位,等等,所以我需要我认为是直位的值。除非有更好的方法,但据我所知,这是我知道如何处理数据的唯一方法。在我的评论中查看上面的链接。我建议您在问题中也确切地提到您的目标是什么,否则我们无法建议您在问题中尝试实现的解决方案更好的方法。
bin
不会让您控制结果字符串的长度,它会预先设置您通常想要切掉的
'0b'
,就像你的代码一样。
格式
功能或方法在这两方面都优于其他方法。例如,
格式(n,'032b')
我在其他问题中看到了这一点。我犹豫使用它的唯一原因是我不知道它是如何工作的。所以join将其中的所有内容都添加到空字符串中。bin(i)将数字转换为二进制,那么[2:]是否去掉了0b前缀?我觉得这已经足够直截了当了,但是为什么b“\x23\x53a”中的for i就在它旁边呢?在bin函数旁边放置for循环做什么?什么是循环?每个字节?@PM2Ring谢谢。我已将其更改为
08b
,因为每个字节都是8位,您无需每次将4个字节转换为int。@Jacob
bin()
将按照@PM2Ring所说的方式修剪字节。我已相应地更新了我的答案。您看到的是一个生成器表达式。在字节上循环,并对每个字节进行格式化。然后使用
str.join()
@Jacob连接所有内容:您可以在Python文档中阅读该方法。字符串用作
.join
的list(或其他迭代器)参数中的子字符串之间的分隔符。那么n是什么?我从struct得到的结果是,“(2370044120,)”表示一个数字。我可以直接传给format吗?另外,python的位运算符是如何工作的?>>换班对吗?&1是做什么的?按位运算符可以处理struct返回的内容吗?对不起,@Jacob,我忘了
struct.unpack
总是返回元组。我已经修复了代码,因此
n
现在是一个Python整数。根据
'>I'
格式规范,它保证是一个无符号的32位数字。@Jacob:是的,
>
是右移,
&
是按位的,因此
c=a&b
对整数
a
b
的相应位执行And运算,将结果放入
c
的相应位。因此,
n&1
计算为
n
的最低有效位。Python按位运算符的工作方式与C和许多其他语言中的工作方式非常相似(除了Python整数没有固定的位宽度这一事实);我想如果你在做一个反汇编程序,你会熟悉位运算符的。:)谢谢你解释这一切。后来我意识到我应该查找struct.unpack返回的内容,我看到它是一个元组。我是f