Python 如何在二进制文件中只打印可打印字符(与Linux下的字符串相等)?

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

我正在将我的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.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')