繁体   English   中英

从python中的二进制文件中提取字符串

[英]extract strings from a binary file in python

我有一个项目,我给了一个文件,我需要从文件中提取字符串。 基本上想到linux中的“strings”命令,但我在python中这样做。 下一个条件是文件作为流(例如字符串)给我,所以使用其中一个子进程函数来运行字符串的明显答案也不是一个选项。

我写了这段代码:

def isStringChar(ch):
    if ord(ch) >= ord('a') and ord(ch) <= ord('z'): return True
    if ord(ch) >= ord('A') and ord(ch) <= ord('Z'): return True
    if ord(ch) >= ord('0') and ord(ch) <= ord('9'): return True

    if ch in ['/', '-', ':', '.', ',', '_', '$', '%', '\'', '(', ')', '[', ']', '<', '>', ' ']: return True

# default out
return False

def process(stream):
dwStreamLen = len(stream)
if dwStreamLen < 4: return None

dwIndex = 0;
strString = ''
for ch in stream:
    if isStringChar(ch) == False:
        if len(strString) > 4:
            #print strString
            strString = ''
    else:
        strString += ch

这在技术上有效,但速度慢。 例如,我能够在500Meg可执行文件上使用strings命令,并且在不到1秒的时间内生成了价值300k的字符串。 我通过上面的代码运行了相同的文件,花了16分钟。

有没有一个库可以让我在没有python延迟负担的情况下做到这一点?

谢谢!

与David Wolever相似的速度,使用re ,Python的正则表达式库。 优化的简短故事是你编写的代码越少,它就越快。 循环的库函数通常在C中实现,并且比您希望的更快。 同样适用char in set()char in set()比检查自己更快。 在这方面,Python与C相反。

import sys
import re

chars = r"A-Za-z0-9/\-:.,_$%'()[\]<> "
shortest_run = 4

regexp = '[%s]{%d,}' % (chars, shortest_run)
pattern = re.compile(regexp)

def process(stream):
    data = stream.read()
    return pattern.findall(data)

if __name__ == "__main__":
    for found_str in process(sys.stdin):
        print found_str

使用4k块工作会很聪明,但是对于带有re边缘情况来说有点棘手。 (其中两个字符位于4k块的末尾,后两个字符位于下一个块的开头)

至少你的一个问题是你正在将整个流读入内存( … = len(stream) ),另一个是你的isStringChar函数非常慢(函数调用相对较慢,你做了很多事情)他们)。

更好的是这样的:

import sys
import string

printable = set(string.printable)

def process(stream):
    found_str = ""
    while True:
        data = stream.read(1024*4)
        if not data:
            break
        for char in data:
            if char in printable:
                found_str += char
            elif len(found_str) >= 4:
                yield found_str
                found_str = ""
            else:
                found_str = ""

 if __name__ == "__main__":
     for found_str in process(sys.stdin):
        print found_str

这将更快,因为:

  • “是字符可打印的”查找是使用一组查找(和O(1)操作)执行的,它直接调用(如果我没有记错的话)进入C函数(这将非常快)。
  • 流以4k块处理,这将改善大输入的内存使用和运行时间,因为不需要交换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM