从二进制文件中提取文本(在Windows7上使用Python2.7)

2024-06-16 10:07:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个大约5MB的二进制文件。。里面有很多穿插的文字。。和控制字符。。在

这实际上相当于SITATEX应用程序的outlook.pst文件(来自SITA)。在

该文件包含所有发送和接收到的来自外部世界的文本消息…(但文本必须通过二进制控制字符提取)。。所有的短信都清晰可见。。。行尾为^M个字符。。。等等

例如:假设^@^X是控制字符。。。\xaa和HEX-aa等。加载它们周围我需要的文本提取。在

^@^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X
^X^X^X
MVT^M
EA1123 TEXT TEXT TEXT^M
END^M
\xaa^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
 ^@^@^@^@^@^@^@^@^@^@^@TTBBTT^X^X^X^X^X^X^X^X^X
   ^X^X^X blah blah blah... of control characters.. and then the message comes..
   MVT MESSAGE 2
   ED1123
   etc.

等等。。好几条消息。在

使用Perl。。很容易做到:

^{pr2}$

如何在python中轻松地做到这一点。。在

  1. 如何读取文件?二进制和文本穿插
  2. 消除不必要的控制字符
  3. 分析两个\xaa有用文本信息\xaa(HEX'aa')之间的消息
  4. 把需要的东西打印出来
  5. 穿过所有的线路。。还有更多的文件。

在文本文件示例中。。。我有兴趣看。。BLLBBC。。。以及MVT和EA1123等等。在

请协助。。。如果在python中很难实现。。我将不得不仔细考虑perl本身的逻辑。。因为它(perl)不会给我带来很多错误,至少对于二进制和文本的循环部分来说。。还有正则表达式。在

谢谢。在

阅读您的答案/评论后更新1月2日

在看过S.Lott的评论和其他人之后。。。这就是我现在所在的地方。。80%的工作正常。在

import fileinput
import sys
import re

strfile = r'C:\Users\' \
          r'\Learn\python\mvt\sitatex_test.msgs'

f = open(strfile, 'rb')

contents = f.read() # read whole file in contents

#extract the string between two \xaaU.. multiline pattern match
#with look ahead assertion
#and this is stored in a list with all msgs
msgs = re.findall(r'\xaaU.*?(?=\xaaU)', contents, re.I|re.DOTALL|re.M)

for msg in msgs:
    #loop through msgs.. to find the first msg then next and so on.
    print "## NEW MESSAGE STARTS HERE ##"

    #for each msg split the lines.. to read line by line
    # stored as list in msglines
    msglines = msg.splitlines()
    line = 0
#then process each msgline with a message
for msgline in msglines:
    line += 1
    #msgline = re.sub(r'[\x00]+', r' ', msgline)
    mystr = msgline
    print mystr
    textstrings = re.findall(r'[\x00\x20-\x7E]+', msgline)

到目前为止还不错。。但我还没完全做完。。因为我需要逐行逐字地分析文本。。收集(例如)原始地址和邮件头、主题行、邮件正文。。。通过控制字符解析消息。在

现在我被困在。。。如何将控制字符转换为\x00\x02..等(使用\xHH格式)逐行打印。。但不要理会正常的可读文本。在

例如。。假设我有这个:假设^@和{}是一些控制字符 line1 = '^@UG^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X'(在第一行)。在

当我在空闲时打印这行。。print line1。。它只显示前2或3个字符。。而忽略其余由于控制字符被掐死。在

但是,当我用这个打印时:print re.findall(r'.*', line1)

['\xaaUG\x02\x05\x00\x04\x00\x00\x00\x05\x00\x00\x00....
x00\x00\x00..BLLBBCC\x00\x00N\x00N\\x00
 002 010 180000 DEC 11', '']

将所有控制字符转换为\xHH格式,打印效果很好。。以及完整的ascii文本。。(正如我所希望的那样)…只抓一次。。这个单子有两项。。以“”结尾。在

  1. 最后空字符串的解释是什么?
  2. 如何避免。。。我只想把这行代码转换成一个字符串(而不是一个列表)。i、 e.将一行二进制/文本转换为带有\xHH代码的字符串。。保留ASCII文本。

使用re.findall(r'.*', line1)是唯一简单的解决方案。。要进行此转换。。或者还有其他直接的方法。。将'\x00string'转换为\xHH和文本(其中它是可打印字符或空白)。在

还有。。有没有其他有用的注释可以很好地表达出来。在

谢谢。在

更新2011年1月2日-第2部分

我发现re.findall(r'.+', line1)

['\xaaUG\x02\x05\x00\x04\x00\x00\x00\x05\x00\x00\x00....
    x00\x00\x00..BLLBBCC\x00\x00N\x00N\\x00
     002 010 180000 DEC 11']

列表中没有多余的空白“”项。在这次审判之后发现了很多错误。在

我仍然需要帮助来完全消除列表,但只返回一个字符串。 像这样:

'\xaaUG\x02\x05\x00\x04..BLLBBCC..002 010 180000 DEC 11'

于1月5日添加信息:

@约翰·麦肯

1)\xaaU是消息之间的分隔符。。在示例中。。我可能刚刚漏掉了样品。请参阅下面的一条以\xaaU结尾的实际消息(但省略了)。 以下文本来自repr(msg between r'\xaaU.*?(?=\xaaU)'

我试图理解二进制格式。。这是发出的典型信息 第第一个'JJJOWXH'是发件人地址。。任何后面有7个字母数字的就是接收器地址。。根据发件人地址。。我能知道这是“SND”还是“RCV”。。因为来源是'JJJOWXH'。。。这个消息是一个'SND',因为我们是'JJJOWXH'。在

邮件地址:JJJKLXH。。。。JJJKRXH。。。。等等。在

一旦。。\x00000000饰面。。 sita标题和主题开始 在这种情况下。。。"\x00QN\x00HX\x00180001 \x00"这是头。。我只对\x00之间的所有东西感兴趣。在

下一个是尸体。。在最后的\x00或任何其他控制字符之后。。。在这种情况下。。。它是:

COR\r\nMVT \r\nHX9136/17.BLNZ.JJJ\r\nAD2309/2314 EA0128 BBB\r\nDLRA/CI/0032/0022\r\nSI EET 02:14 HRS\r\n RA / 0032 DUE TO LATE ARVL ACFT\r\n CI / 0022 OFFLOAD OVERHANG PALLET DUE INADEQUATE PACKING LEADING TO \r\n SPACE PROBLEM

一旦可读文本结束。。。将忽略直到\xaaU结尾出现的第一个控制字符。。。在上述情况下空间问题”。。是最后一个。。然后控制字符开始。。。所以被忽视。。。有时控制字符直到下一个\xaaU才会出现。在

这是一个完整的信息。在

"\xaaU\x1c\x04\x02\x00\x05\x06\x1f\x00\x19\x00\x00\x00\xc4\x9d\xedN\x1a\x00?\x02\x02\x00B\x02\x02\x00E\x02\x07\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00M\x02\xec\x00\xff\xff\x00\x00\x00\x00?\x02M\x02\xec\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00:\x03\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00JJJOWXH\x00\x05w\x01x\x01\x00\x01JJJKLXH\x00\x00\x7f\x01\x80\x01\x00\x01JJJKRXH\x00F\x87\x01\x88\x01\x00\x01JJJFFXH\x00\xff\x8f\x01\x90\x01\x00\x01JJJFCXH\x00\xff\x97\x01\x98\x01\x00\x01JJJFAXH\x00\x00\x9f\x01\xa0\x01\x00\x01JJJKPXH\x00\x00\xa7\x01\xa8\x01\x00\x01HAKUOHU\x00\x00\xaf\x01\xb0\x01\x00\x01BBBHRXH\x00\x00\xb7\x01\xb8\x01\x00\x01BBBFFHX\x00\x00\xbf\x01\xc0\x01\x00\x01BBBOMHX\x00\x00\xc7\x01\xc8\x01\x00\x01BBBFMXH\x00\x00\xcf\x01\xd0\x01\x00\x01JJJHBER\x00\x00\xd7\x01\xd8\x01\x00\x01BBBFRUO\x00\x00\xdf\x01\xe0\x01\x00\x01BBBKKHX\x00\x00\xe7\x01\xe8\x01\x00\x01JJJLOTG\x00\x01\xef\x01\xf0\x01\x00\x01JJJLCTG\x00\x00\xf7\x01\xf8\x01\x00\x01HDQOMTG\x005\xff\x01\x00\x02\x00\x01CHACSHX\x00K\x07\x02\x08\x02\x00\x01JJJKZXH\x00F\x0f\x02\x10\x02\x00\x01BBBOMUO\x00 \x17\x02\x18\x02\x00\x01BBBORXH\x00 \x1f\x02 \x02\x00\x01BBBOPXH\x00W'\x02(\x02\x00\x01CHACSHX\x00 /\x020\x02\x00\x01JJJDBXH\x0007\x028\x02\x00010000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00\x00000000\x00QN\x00HX\x00180001 \x00COR\r\nMVT \r\nHX9136/17.BLNZ.JJJ\r\nAD2309/2314 EA0128 BBB\r\nDLRA/CI/0032/0022\r\nSI EET 02:14 HRS\r\n RA / 0032 DUE TO LATE ARVL ACFT\r\n CI / 0022 OFFLOAD OVERHANG PALLET DUE INADEQUATE PACKING LEADING TO \r\n SPACE PROBLEM\x00D-\xedN\x00\x04\x1a\x00t<\x93\x01x\x00M_\x00"

2)知道“repr”后,我不再使用。+了。在

3)每条消息都是多行的。。我需要保留所有的控制字符来理解这个专有格式。。这就是为什么我需要雷普近距离观察。在

希望这能解释。。。这只是1000个邮件中的1个。。。有些是“SND”,有些是“RCV”。。。而对于'RCV'就不会有'000000'。。偶尔也有例外。。。但通常这是可以的。在

有什么进一步的建议吗。。我还在处理文件。。要完整地检索文本。。。有发送方和接收方地址。在

谢谢。在


Tags: 文件文本re消息二进制x00x01x02
3条回答

Python也支持regex。我不会说Perl,所以我不知道您的Perl代码到底是做什么的,但是这个Python程序可能会帮助您:

import re
with open('yourfile.pst') as f:
    contents = f.read()
textstrings = re.findall(r'[\x20-\x7E]+', contents)

这将得到文件中包含一个或多个ASCII可打印字符的所有字符串的列表。这可能不是你想要的,但是你可以从那里调整它。

请注意,如果您使用的是python3,那么您必须担心二进制数据和文本数据之间的区别,这会变得更加复杂。我假设你在python2中。

你说:

Still I will need assistance to eliminate the list altogether but return just a string. like this

换句话说,你有foo = [some_string],你正在做print foo,作为一个边,repr(some_string)但是你不想用方括号括起来。所以只要做print repr(foo[0])

似乎有几件事无法解释:

  1. 您说有用的文本用\xaaU括起来,但是在示例文件中,在开头附近只有\xaa(缺少U),而没有其他内容。

  2. 你说呢

    I have found out that re.findall(r'.+', line1) strips to ...

    实际上是剥离\n(但不是\r!!)我认为在尝试恢复电子邮件时,换行是值得保留的。

    >>> re.findall(r'.+', 'abc\r\ndef\r\n\r\n')
    ['abc\r', 'def\r', '\r']
    

    你对\r字符做了什么?你测试过多行信息吗?你测试过多消息文件吗?

  3. 一个人可以猜测谁或什么人打算消耗你的输出;你写

    I need to parse the text line by line and word by word

    但你似乎过于关心用\xab而不是乱七八糟地打印消息。

  4. 最新代码中的最后6行左右(for msgline in msglines:等)应该缩进一级。

有没有可能澄清以上所有的问题?

问:如何读取文件?二进制和文本穿插在一起

A:不用麻烦,只要把它当作普通文本来读,你就可以保持你的二进制/文本二分法(否则你就不能很容易地对它进行正则表达式)

fh = open('/path/to/my/file.ext', 'r')
fh.read()

如果以后出于某种原因想读取二进制文件,只需在open的第二个输入中添加一个b:

^{pr2}$

Q:消除不必要的控制字符

A:使用pythonre模块。你的下一个问题是如何

Q:解析两个\xaa有用文本信息之间的消息\xaa(HEX'aa')

A:re模块有一个findall函数,它的工作方式与您(大多数)期望的一样。

import re

mytext = '\xaaUseful text that I want to keep\xaa^X^X^X\xaaOther text i like\xaa'
usefultext = re.findall('\xaa([a-zA-Z^!-~0-9 ]+)\xaa', mytext)

Q:打印出所需资料

*A:有一个打印功能。。。

print usefultext

Q:把所有的线都圈起来。。以及更多文件。

fh = open('/some/file.ext','r')

for lines in fh.readlines():
    #do stuff

我将让您找出os模块来确定存在哪些文件/如何遍历它们。

相关问题 更多 >