簡體   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