проанализировать файл с текстом (с информацией о смещении) и двоичными данными в Python - PullRequest
0 голосов
/ 22 ноября 2010

У меня есть XML-файл, который содержит набор тегов текстовых элементов (каждый из которых содержит десятичное значение смещения и длину данных соответствующего двоичного элемента) и полные двоичные данные всех элементов в конце.Ниже приведен пример.

<?xml version="1.0" encoding="UTF-8"?>
<Package>
  <element>
        <offset>0</offset>
        <length>2961181</length>
        <checksum>4238515972</checksum>
        <format>gzip</format>
  </element>
  <element>
        <offset>2961181</offset>
        <length>5442</length>
        <checksum>4238515972</checksum>
        <format>bin</format>
  </element>
</Package>
BINARY_DATA

обратите внимание, смещение является десятичным и отсчитывается от первого байта после заголовков.Как я могу проанализировать этот файл в Python, получить соответствующий элемент на основе смещения, распаковать его (если его формат gzip) и сохранить его в виде файла?

хорошо, на основе ответов от OmnipotentEntity и Jakob_BЯ сделал следующий короткий скрипт, просто чтобы посмотреть, работает ли он для 1-го элемента:

import zlib

f = open("file.xml", "r")
text = f.read()
position = text.find("</Package>\n")
headerSize=position+ len("</Package>\n") + 1 
offset=0
f.seek(headerSize + offset) 
length = 2961181
bin_data = f.read(length)
zipped=1
if (zipped):
  ungziped_str = zlib.decompressobj().decompress('x\x9c' + bin_data)
  print(ungziped_str)
f.close()

, однако я получил следующую ошибку:

Traceback (последний вызов был последним):Файл "file_parse.py", строка 11, в?ungziped_str = zlib.decompressobj (). depress ('x \ x9c' + bin_data) zlib.error: Ошибка -3 при распаковке: неверный тип блока

в чем проблема?входной файл неверный, или код неверный?

Ответы [ 3 ]

2 голосов
/ 22 ноября 2010

Хитрость заключается в том, чтобы не допустить разбора XML-парсерами двоичных данных. lxml позволяет вам одновременно передавать строку в анализатор, чтобы вы могли следить за последним тегом XML и останавливаться на достигнутом:

from lxml import etree

def process(filename):
    f = file(filename,"r")
    parser = etree.XMLParser()
    for l in f:
        parser.feed(l)
        if l=="</Package>\n":
            break
    return parser.close()

Возвращает

r=process("junk.xml")
<Element Package at 9f14eb4>

, который является объектом lxml, из которого вы можете получить данные. Смещение второго объекта здесь:

>>> r[1][0].text
'2961181'

и так далее. Этого должно быть достаточно для вас, чтобы сделать работоспособное решение. Остерегайтесь окончания строки в теге Package, хотя может быть лучший способ сделать это, это может не сработать, если файл имеет другое окончание строки.

1 голос
/ 22 ноября 2010

Почему бы не запустить поиск конечного тега с помощью lxml?Затем, когда конечный тег найден, просто .seek () до этого момента и считывает двоичные данные.

0 голосов
/ 22 ноября 2010

Определите размер заголовка.

Смещение захвата и длину данных с использованием xml magic

import zlib
python.seek(headerSize+offset)
mydata = python.read(length)
if (zipped):
  ungziped_str = zlib.decompressobj().decompress('x\x9c' + mydata)

Затем запишите в файл как обычно.

Источник для gunzip magic http://codingrecipes.com/ungzip-a-string-in-python-gzinflate-in-python

...