Извлечь текст из двоичного файла (используя Python 2.7 в Windows 7)

1

У меня есть двоичный файл размером около 5 МБ.., который содержит много перемежаемого текста.. и управляющие символы.

Это фактически эквивалент Outlook.pst файла для приложения SITATEX (от 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.. легко сделать:

while (<>) {
  use regular expression to split messages
  m/   /


}

Как можно сделать это на python легко..

  1. Как читать файл? двоичный и текст вкраплены
  2. Устранить ненужные управляющие символы
  3. разобрать сообщения между двумя \xaa ПОЛЕЗНАЯ ИНФОРМАЦИЯ ТЕКСТА \xaa (HEX 'aa')
  4. распечатать необходимый материал
  5. Прокрутите все строки.. и больше файлов.

В образце текстового файла... мне интересно видеть.. BLLBBCC... и MVT и EA1123 и так далее.

Пожалуйста, помогите... Если это будет очень сложно в python.. Мне придется продумать логику в perl себе.. поскольку он (perl) не бросает много ошибок у меня, по крайней мере, для цикла бинарного и текстового материала.. и регулярное выражение.

Благодарю.

Обновление 02Jan после прочтения ваших ответов/комментариев

Пройдя через комментарии С.Лотта и другие... Вот где я нахожусь.. и он работает на 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.. т \x00\x02.. Д. (Используя формат \xHH).., но оставляйте обычный читаемый текст в покое.

Например, скажем, у меня есть это: предположим, что ^@ и ^X - некоторые управляющие символы: line1 = '^@UG^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X' (в первой строке).

Когда я печатаю строку так, как она есть в IDLE.. 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. Как этого избежать... Я просто хочу, чтобы строка была хорошо преобразована в строку (а не список). т.е. одна строка двоичного/текстового текста, которая должна быть преобразована в строку с кодами \xHH. Оставьте только ASCII TEXT.

Является ли использование re.findall(r'.*', line1) единственным удобным решением.. для этого преобразования.. или есть какой-либо другой простой метод.. преобразовать '\x00string' в \xHH и TEXT (где это печатный символ или пробел).

Также.. любые другие полезные комментарии, чтобы получить строки хорошо.

Благодарю.

Обновление 2Jan2011 - часть 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'

Добавлена информация о 05Jan:

@John Machin

1)\xaaU является разделителем между сообщениями. В примере.. Возможно, я просто оставил в выборках. Ниже приведено одно фактическое сообщение, которое заканчивается на \xaaU (но не указано). После текста получается сообщение (msg между r'\xaaU.*?(?=\xaaU)')

Я пытаюсь понять двоичный формат. Это типичное сообщение, которое отправляется первым "JJJOWXH" - это адрес отправителя. Все, что следует за ним, имеет 7 буквенно-цифровых адресов получателя. На основе адреса отправителя.. Я могу узнать, является ли это "SND" или "RCV".. поскольку источником является "JJJOWXH"... Этот msg является "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 ПОЗДНУЮ АРВЛЕРНУЮ ПРОДУКЦИЮ CI/0022 ОТКРЫТЬ ПЕРЕГРУЗЧИК ПАДЕНИЯ В НЕПРАВИЛЬНОМ УПАКОВКЕ В ЛИДЕРЕ В ПРОСТРАНСТВЕННОЙ ПРОБЛЕМЕ

после завершения чтения прочитанного текста... первый символ управления, который появляется до конца \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\X Е8\x01\x00\x01JJJLOTG\x00\x01\ХеР\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\x01BBOPXH\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 ПОСЛЕДУЮЩАЯ АРВТНАЯ АКФТ \r\n CI/0022 ОТКРЫТЬ ПЕРЕГРУЗЧИК ПАДЕНИЯ ВНУТРИ НЕЗАКОННОГО УПАКОВКИ TO\r\n ПРОСТРАНСТВЕННАЯ ПРОБЛЕМА \x00D-\xedN\x00\x04\x1a\x00t <\ x93\x01x\x00M_\x00 "

2) Я больше не использую. + После того, как "репрезентация" известна.

3) каждое сообщение является многострочным.. и мне нужно сохранить все контрольные символы, чтобы понять смысл этого проприетарного формата.. вот почему мне нужен реестр, чтобы увидеть его близко.

Надеюсь, это объяснит... Это всего лишь 1 сообщение из 1000 с файлом... и некоторые из них "SND", а некоторые - "RCV"... и для "RCV" не будет "000000". и иногда есть незначительные исключения из правила... но обычно это нормально.

Любые дополнительные предложения кому-либо. Я все еще работаю с файлом.., чтобы восстановить текст без изменений... с адресами отправителя и получателя.

Спасибо.

  • 3
    Откажитесь от Perl. Что вы пробовали до сих пор в Python? Мы не знаем, как много вы знаете, что вы пробовали или что вас смущает. Это довольно тривиальные вещи (правда). Python использует пакет re library, например, чтобы делать то, что Perl делает с оператором m/.../ .
  • 0
    Я перепробовал все .. findall .. re ... sub ... replace ... читать построчно ... символ за символом ... я не мог заставить его работать ... все, что я хочу, это просто текст между двумя \ xaa (Hex) ... Файл останавливается из-за управляющих символов, включая EOF и другие бессмысленные символы, которые я понятия не имею ... Обратите внимание, что файл, который я читаю, является проприетарным форматом ... имеет весь код символов ... и меня интересует только смешанный ТЕКСТ между этими символами ... Только после того, как я преодолел первое препятствие при разборе текста ... Я могу пройти через логику выбора вещей, которые мне нужны.
Показать ещё 4 комментария
Теги:
text-extraction

3 ответа

1
Лучший ответ

Ты говоришь:

Тем не менее мне понадобится помощь, чтобы полностью исключить список, но верните только строку. как это

Другими словами, у вас есть foo = [some_string] и вы делаете print foo который, как сторона делает repr(some_string) но заключает его в квадратные скобки, которые вы не хотите. Поэтому просто print repr(foo[0]).

Кажется, что есть несколько вещей, необъяснимых:

  1. Вы говорите, что полезный текст заключен в скобки по \xaaU но в примере файла вместо 2 вхождений этого разделителя есть только \xaa (отсутствует U) рядом с началом, и ничего больше.

  2. Ты говоришь

    Я обнаружил, что re.findall(r '. +', Line1) разбивает на...

    Это фактически отключает \n (но не \r !!) - я думал, что разрывы строк будут сохранены при попытке восстановить сообщение электронной почты.

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

    То, что вы сделали вы с \r символов? Вы протестировали многострочное сообщение? Вы протестировали файл с несколькими сообщениями?

  3. Нужно угадать, кто или что предназначен для потребления вашей продукции; ты пишешь

    Мне нужно разобрать текст по строкам и слово за словом

    но вы, похоже, слишком озабочены печатью сообщения "разборчиво", например, \xab вместо тарабарщины.

  4. Похоже, что последние 6 или около того строк в вашем последнем коде (for msgline in msglines: etc и т.д.) Должны быть отступом на один уровень.

Можно ли прояснить все вышесказанное?

  • 1
    @JohnM .. Ух ты !!! repr (некоторый текст с двоичным кодом) возвращает строковое представление .. превосходно. Я понятия не имею, почему я не могу найти в сети кого-нибудь, кто бы порекомендовал это, пока я искал это ... они говорили только о некотором bin2ascii .. hexlify .. struct .. бла-бла-бла -... все из которых являются бесполезен для моих нужд ... Большое спасибо ... Остальные вопросы ... позвольте мне вернуться к вам завтра с объяснениями ... Еще раз спасибо.
  • 0
    @JohnM .. Я добавил еще одну добавленную заметку в свой первоначальный вопрос ... начиная с "Дополнительная информация о 05Jan:"
2

В: Как прочитать файл? двоичный и текст вкраплены

A: Не утруждайте себя, просто прочитайте его как обычный текст, и вы сможете сохранить двоичную/текстовую дихотомию (иначе вы не сможете повторно использовать ее так же легко)

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

На всякий случай, если вы хотите по какой-то причине почитать двоичный код, вы просто добавляете ab ко второму входу open:

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

Q: Устранить ненужные управляющие символы

A: Используйте модуль python re. Ваш следующий вопрос sorta спросит, как

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, чтобы выяснить, какие файлы существуют/как проходить через них.

2

Python также поддерживает регулярные выражения. Я не говорю на Perl, поэтому я не знаю точно, что делает ваш код Perl, но эта программа Python может вам помочь:

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

Это даст вам список всех строк одного или нескольких ASCII печатных символов в файле. Это может быть не совсем то, что вы хотите, но вы можете настроить его там.

Обратите внимание: если вы используете Python 3, вам придется беспокоиться о различии между двоичными и текстовыми данными, и это становится немного сложнее. Я предполагаю, что вы на Python 2.

  • 0
    В файле есть все виды управляющих символов, включая EOF hex (1A). Когда я использовал ваш код с небольшими изменениями, чтобы прочитать файл построчно и проанализировать содержимое ... сценарий преждевременно останавливается из-за всех этих управляющих символов ... как достигается EOF ... в первых 3 строках ... все еще Более 10000 строк. Я использую Python 2.7 .... В Perl .. когда я делаю такой цикл по строкам ... он таинственным образом без проблем может пройти по всем строкам ... и сопоставить содержимое ... Как я изучаю Python .. Я хочу попробовать сделать это Python способом ...
  • 2
    Это винда? Если это так, пожалуйста, включите тег [Windows] в свой вопрос. У Линуса нет такого "EOF" персонажа. Пожалуйста, попробуйте что-то вроде open('yourfile.pst','rb') которое может преодолеть глупость Windows.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню