Python 如何在二进制文件中只打印可打印字符(与Linux下的字符串相等)?
我正在将我的python应用程序从python 2转换为python 3。我使用的函数之一是从二进制文件中获取可打印字符。我之前在python 2中使用了以下函数,效果非常好:Python 如何在二进制文件中只打印可打印字符(与Linux下的字符串相等)?,python,string,python-3.x,Python,String,Python 3.x,我正在将我的python应用程序从python 2转换为python 3。我使用的函数之一是从二进制文件中获取可打印字符。我之前在python 2中使用了以下函数,效果非常好: import string def strings(filename, min=4): with open(filename, "rb") as f: result = "" for c in f.read(): if c in string.printa
import string
def strings(filename, min=4):
with open(filename, "rb") as f:
result = ""
for c in f.read():
if c in string.printable:
result += c
continue
if len(result) >= min:
yield result
result = ""
if len(result) >= min: # catch result at EOF
yield result
代码实际上来自。当我使用python 2运行上述代码时,它会生成如下输出,这对我来说绝对是好的:
+s
^!1^
i*Q(
}"~
%lh!ghY
#dh!
!`,!
mL#H
o!<XXT0
' <
z !Uk
%
wS
n` !wl
*ty
(Q 6
!XPLO$
E#kF
用这个
if str(c) in string.printable:
(我还转换了抛出相同错误消息的所有位置)
现在,python 3提供以下输出:
56700
0000000000000000000000000000000000000000
1236
60000
400234
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2340
0000
5010
5000
17889
2348
23400000000
5600
当我使用python 3时,我看不到任何字符。任何帮助代码工作或指向解决方案的指针都将不胜感激。我所需要的就是从二进制文件(非常小,只有几kb)中提取字符串并将其存储在变量中。在Python 3中,以二进制模式打开一个文件会得到
字节的结果。在字节
对象上迭代会得到0到255(包括0到255)范围内的整数,而不是字符。从:
虽然字节文字和表示基于ASCII文本,字节
对象实际上表现为不可变的整数序列,序列中的每个值都受到限制,因此0
我相信这会奏效的
作为发电机:
导入字符串,\u io
def getPrintablesFromBinaryFile(路径,encoding='cp1252'):
全局io,字符串
buffer=_io.BufferedReader(打开(路径'rb'))
尽管如此:
字节=缓冲区。读取(1)
如果字节==b“”:
返回#EOF
尝试:
d=字节。解码(编码)
除:
持续
如果在string.printable中为d:
产量d
函数的作用是将getPrintablesFromBinaryFile()的输出收集到iterable中
说明:
导入所需的模块
定义函数
加载模块
创建缓冲区
从缓冲区中获取一个字节
检查是否为EOF
如果是,停止发电机
尝试使用编码进行解码(如“\xef”
不使用UTF-8进行解码)
如果不可能,则不能打印
如果可以打印,则生成它
注意:cp1252
是许多文本文件的编码在python3中有字节。使用set(string.printable.encode())
我不知道是谁否决了这个问题。但我要求他们像“Martijn Pieters先生”在回答中那样展示文件和解释。如果显示,我将删除此帖子/问题,并使用result=b”“
。@MarkTolonen:最好使用bytearray
;不能将整数附加到字节
对象中..没错,这是一件令人惊讶的事情。迭代str
得到长度为1的strs,但迭代字节
得到整数<代码>字节数组
无论如何都是可变的<代码>结果+=字节([c])
可以工作,但效率不高。为什么使用\u io
而不使用io
?而且open()
已经返回了一个缓冲读取器,为什么要再次包装它?为什么要用任意的8位编解码器解码?字符串中的所有字符。可打印的
均为ASCII字符;最好在解码之前检测这些,并避免这种开销。由于一次只读取1个字节,所以无论如何都不能使用任何多字节编解码器;以文本模式打开文件会更符合逻辑。此外,除语句外,不要使用笼统的;而是捕获特定的异常。操作代码生成整个字符串,您生成单个字节,这是没有帮助的。
if str(c) in string.printable:
56700
0000000000000000000000000000000000000000
1236
60000
400234
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2340
0000
5010
5000
17889
2348
23400000000
5600
printable = {ord(c) for c in string.printable}
if c in printable:
printable = {ord(c) for c in string.printable}
with open(filename, "rb") as f:
result = bytearray()
for c in f.read():
if c in printable:
result.append(c)
continue
if len(result) >= min:
yield result.decode('ASCII')
result.clear()
if len(result) >= min: # catch result at EOF
yield result
import re
nonprintable = re.compile(b'[^%s]+' % re.escape(string.printable.encode('ascii')))
with open(filename, "rb") as f:
for result in nonprintable.split(f.read()):
if result:
yield result.decode('ASCII')
with open(filename, "rb") as f:
buffer = b''
for chunk in iter(lambda: f.read(2048), b''):
splitresult = nonprintable.split(buffer + chunk)
buffer = splitresult.pop()
for string in splitresult:
if string:
yield string.decode('ascii')
if buffer:
yield buffer.decode('ascii')