2010-11-22 1 views
0

텍스트 요소 태그 세트 (각 십진 오프셋 값과 해당 바이너리 요소의 데이터 길이 포함)가 포함 된 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 

오프셋은 10 진수이며 헤더 뒤의 첫 번째 바이트부터 계산됩니다. 어떻게 파이썬에서이 파일을 구문 분석하고 오프셋을 기반으로 해당 요소를 잡아서 압축을 풀고 (해당 형식이 gzip 인 경우) 압축하여 파일로 저장할 수 있습니까? OmnipotentEntity 및 Jakob_B의 응답에 따라 잘

가, 난 그냥이 첫번째 요소에 대해 작동하는지 확인하기 위해, 다음과 같은 간단한 스크립트를 만들어 : 그러나

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() 

, 나는 다음과 같은 오류가 발생했습니다 :

추적 (가장 최근 통화 마지막) : 파일 "file_parse.py"11 번 줄? ungziped_str = zlib.decompressobj() 압축 해제 ('X \ x9c'+ bin_data) zlib.error :. 유효하지 않은 블록 타입

문제가 무엇 : 오류 -3 압축을 푸는 동안? 입력 파일이 잘못되었거나 코드가 올바르지 않습니까?

+0

테스트 XML (XML 다음에 BINARY_DATA가있는 테스트 XML)에서 실행하고 테스트를 위해 길이를 10으로 설정하면 "INARY_DATA"가 표시됩니다. 프로그래밍에 버그가 3 가지 밖에 없다는 것을 기억하십시오 : 예기치 않은 입력과 하나씩 오류가 있습니다. – Spacedman

+0

감사합니다, Spacedman, off-by-one 오류, headerSize = position + len (" \ n")으로 변경되었지만 여전히 다른 오류가 발생했습니다 : ungziped_str = zlib.decompressobj(). decompress ('x \ x9c'+ bin_data) zlib.오류 : 압축을 푸는 동안 오류 -3 : 저장 블록 길이가 잘못되었습니다. – pepero

+0

우리가 파일을 재생하지 않고 디버깅하기가 어려울 수 있습니다. 가급적 큰 toooooo하지 않는 것이 좋습니다. – Spacedman

답변

2

트릭은 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() 

당신이 할 수있는 LXML 객체 인

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

를 돌려 데이터를 꺼내라. 두 번째 객체의 오프셋은 다음과 같습니다.

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

등등. 그것은 당신이 실행 가능한 솔루션을 만들기에 충분해야합니다. 그러나 패키지 태그에서 끝나는 줄을주의하십시오. 더 좋은 방법이있을 수 있습니다. 파일에 다른 줄 끝이 있으면이 방법이 작동하지 않을 수 있습니다.

+0

예! 이것이 올바른 방법입니다. 파서를 줄 단위로 먹이는 것을 나는 몰랐다. @pepero : 독점적 저장 방법입니까? – vonPetrushev

0

헤더 크기를 결정하십시오.

잡아 오프셋 및 데이터 길이 그리고 정상적으로 파일에 쓸 수

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

마법 XML을 사용. 왜 LXML를 사용하여 종료 태그에 대한 검색을 실행하지 http://codingrecipes.com/ungzip-a-string-in-python-gzinflate-in-python

+0

필자가 이해했듯이 xml 헤더를 파싱하기 전에 오프셋에 대한 지식이 없습니다. 또한 위의 예제에서 xml에 지정된 두 개의 이진 부분이 있습니다. 진짜 문제는 XML을 읽고 구문 분석하는 방법입니다. XML이 어디에서 끝나는 지 알 수 없기 때문입니다. – vonPetrushev

+0

안녕하세요, OmnipotentEntity, 답변 해 주셔서 감사합니다. vonPetrushev가 지적했듯이 offset 값 등에 대한 지식이 없으므로 xml은 먼저 문자열로 읽혀 야하고 모든 요소의 (오프셋, 길이) 쌍의 데이터 구조를 작성한 다음 seek/unzip하는 방식으로 제공됩니다 /쓰다. 이것이 맞다면, 어떤 (오프셋, 길이) 쌍 부분이 될 것입니까? – pepero

1

마법 gunzip을위한

소스? 그런 다음 종료 태그가 발견되면 해당 위치로 .seek()를 검색하고 바이너리 데이터를 읽습니다.

관련 문제