这似乎是一种应该有很多重复和大量答案的问题,但我的搜索只导致沮丧和没有可用的解决方案。
在Python(最好是3.x)中,我想知道如何打开任意类型的文件,读取存储在磁盘上的字节,并在对其进行任何编码之前以最'本机','原始','原始'的形式呈现这些字节。
如果文件作为00010100 10000100 ...
流存储在磁盘上,那么这就是我想在屏幕上显示的内容。
在您将此标记为重复之前,请确保您心中的答案确实回答了问题(而不仅仅是讨论编码等)。谢谢你!
编辑前三个答案后:
感谢到目前为止的三位响应者,特别是J.F. Sebastian的深入讨论。从上面所说的看来,我的问题归结为如何将文件中的字节物理地记录到磁盘上,以及如何读取和显示它们。在这一点上,在Python中似乎不可能获得原始形式的字节视图,但它们有各种表示形式;整数,十六进制值,ascii等。由于这件事还没有解决,我将把这个问题留给更多的人来回答。
如果你不介意字节:
with open('yourfile', 'rb') as fobj:
raw_bytes = fobj.read()
print(raw_bytes)
如果你真的想要二进制:
with open('yourfile', 'rb') as fobj:
raw_bytes = fobj.read()
print(' '.join(map(lambda x: '{:08b}'.format(x), raw_bytes)))
'rb'
模式允许您从Python文件中读取原始二进制数据:
with open(filename, 'rb') as file:
raw_binary_data = file.read()
type(raw_binary_data) == bytes
。bytes
是Python中不可变的字节序列。
不要混淆字节和它们的文本表示:print(raw_binary_data)
会显示数据的文本表示,例如,一个字节127
(基数为10:十进制),你可以用
表示bin(127) == '0b1111111'
(基数2:二进制)或hex(127) == '0x7f'
(基数16:十六进制)显示为b'x7f'
(打印7个ascii字符)。来自可打印ascii范围的字节被表示为相应的ascii字符,例如,b'x41'
显示为b'A'
(65 == 0x41 == 0b1000001
)。
0x7f
字节不存储为7位ascii二进制数字1111111
,不存储为2位ascii十六进制数字7F
,不存储为3位文字十进制数字127
。b'x7f'
是字节的文本表示形式,可用于在Python源代码中指定它(您也不会在磁盘上找到七个ascii字符的b'x7f'
)。下面的代码将一个单个字节写入磁盘:
with open('output.bin', 'wb') as file:
file.write(b'x7f')
必须使用某种字符来表示字节,它们是什么?
操作系统接口(访问磁盘等硬件的方式)是根据字节定义的,例如,POSIX read(2)也就是说,字节在这里是一个基本单位:你可以直接读/写字节——你不需要任何中间表示。看看理查德·费曼吧。为什么。
字节是如何表示的物理是在操作系统驱动程序和硬件之间的——它可能是任何东西——你不需要担心它:它隐藏在统一的操作系统接口后面。请参阅数据是如何在硬盘驱动器中进行物理写入、读取和存储的?
你可以在Python中直接调用os.read()
,但你不需要它;file.read()
为您完成(Python 3文件对象直接在POSIX接口上实现)。Python 2 I/O使用C studio库,而C studio库又使用OS接口来实现其功能)。
正如您所指出的,这取决于操作系统驱动程序和硬件来确定字节是如何写入的,但Python解释器随后将能够读取它们。它在读取什么东西,那是什么?它不是读取磁盘上粒子的磁性方向,对吧?它正在读取一些符号,我想要访问它。
正在读取字节。硬盘是一台小型计算机,因此有趣的事情可能会发生,但它不会改变,它一直是字节(就"符号"或软件而言)。
《CODE》一书《计算机硬件和软件的隐藏语言》非常温和地介绍了信息是如何在计算机中表示的——"字节"这个词直到第180页才被定义。要了解计算机中使用的抽象层次,"从NAND到俄罗斯方块"课程可以提供帮助。
Python 3表示文件数据为bytes
。类型基本上是一个从0到255的整数列表,所以是一个字节列表。它们有一些方便的方法(例如解码为字符串),并且它们在打印时与字符串类似。
要获得逐位表示,在打开文件时应该使用b
模式。
bin()
将帮助您将整数转换为二进制表示。但是,您可能必须去掉前两个字符,并用0
s填充。
with open(filename, 'rb') as my_file:
my_bytes = my_file.read()
bin_list = [bin(i)[2:].rjust(8, '0') for i in my_bytes]
print(' '.join(bin_list))
在浏览了一些文档之后,Python似乎没有提供直接操作其数据的物理存储的接口。
相反,数据存储的处理传递给操作系统。这没有明确说明,但我从它的io模块文档中得到了印象。
如果你有一个存储为0110100001100101011011000110110001101111
的文件,你用open()
打开它。Python将通过与您的操作系统交互来获取其信息,并最终返回给您一个bytes
对象,通过该对象,您可以查看其不同格式的内容(例如带有b
前缀或十六进制的文本字符串)。
然而,以这种方式(即纯二进制0
和1
)实际存储二进制文件是棘手的,因为大多数程序不支持它。大多数情况下,它们都是间接地完成的:您指定内容的表示形式,要么是x68x65x6cx6cx6f
,要么是带有编码的b'hello'
,然后程序和操作系统完成繁重的工作,并将其放回0110100001100101011011000110110001101111
。
如果我说错了请纠正我:)