2014-03-26 3 views
0

일반적으로 gzip으로 압축 된 일부 파일에서 이진 데이터를 읽어야합니다. 나는 GZIP 모듈을 사용하여 데이터를 읽고 처리했다 : Python : 가끔 압축 된 파일에서 데이터를 읽지 못함 가끔

def decode(self, filename): 
    with gzip.open(filename, 'rb') as f: 
     # ReadData 

그러나 때로는 파일은이 경우 내가 얻을 압축되지 IOError가 (파일이 GZIP 헤더를 가지고 있지 않기 때문에).

내가 좋아하는 뭔가를 할 수 :

try: 
    f = gzip.open(filename, 'rb') 
    f._read_gzip_header() 
    f.rewind() 
except IOError: 
    f.close() 
    f = open(filename, 'rb') 

with f as gz: 
    #ReadData 

을하지만 난 그것을 고칠 수있는 좋은 방법입니다 생각하지 않습니다.

이 문제를 해결하는 우아한 해결책을 찾고 있습니다. 필자는 여러 파일 유형에 대해 여러 "디코드"함수를 작성합니다. 내가 고려하는 솔루션은 GzipFile의 하위 클래스를 작성하여 처리하는 것이지만 더 나은 방법이있을 수 있다고 생각합니다.

저는 파이썬 2.7을 사용하고 있습니다.

미리 제안 해 주셔서 감사합니다!

+1

솔루션에 어떤 문제가 있습니까? 파일을 닫은 다음 즉시 다시 열지는 않겠지 만 try/except를 사용하여 잠재적 인 IOError를 처리하는 것이 정확합니다. 'IOError' 추적을 제외한 일반 텍스트로 읽은 IOError를 제외하고 gzip으로 읽으려고합니다. 그런 다음 파일이 어떻게 열렸는 지 알지 못하는 처리 코드로 모든 처리를 깨끗하게 처리하십시오. –

+0

음, 아마도 내 솔루션에 문제가 없다. (나는 파이썬에 익숙하지 않았으며 때로는 무엇이 좋고/틀린 지 의심 스럽다.) 필자는 적어도 6 개의 디코드 함수 (6 가지 파일 유형)를 작성하고 모든 함수에서 try-except 블록을 작성하는 것을 피할 수있는 더 나은 방법이있을 수 있다고 생각하여 솔루션을 좋아하지 않는 이유가있었습니다 . 하지만 귀하의 의견에 감사드립니다. – user3466240

+0

문제가 코드를 복제하고 싶지 않다면 입력 압축 여부와 상관없이 압축되지 않은 데이터가 포함 된 파일과 유사한 객체를 생성하는 새로운 컨텍스트 관리자를 만듭니다. 다음은 네임드 파이프 생성을 캡슐화하는 contextmanager'named_pipe()'의 코드 예제입니다. (http://stackoverflow.com/a/22435492/4279) – jfs

답변

1

처음 두 바이트 \x1f\x8b을 경우 RFC 1952에 따라 당신은 확인할 수 있습니다 :이 고정이

회원 헤더와 트레일러

ID1 (식별 1) ID2 (식별 2) 파일을 gzip 형식으로 식별하려면 ID1 = 31 (0x1f, \ 037), ID2 = 139 (0x8b, \ 213) 값을 사용하십시오.

그래서 예를 들어

,

with open('test.gz','rb') as f: 
    print(f.read(2)) 

b'\x1f\x8b' #well, that was gzipped 

with open('test','rb') as f: 
    print(f.read(2)) 

b'he' #must not be gzipped 

은 아마도 당신은 그 f.seek(0), 두 바이트에 따라 약간의 제어 흐름을 할 것이라고하고 그에 따라 진행합니다.

솔직히? 귀하의 솔루션은 괜찮습니다 (불필요한 닫기/다시 열 부분을 모듈로). try/except은 pythonic입니다.

+0

답해 주셔서 감사합니다. (2 비트 연금술사에 대한 내 의견도 여기에 적용됩니다.) 그러나 코드의 어느 부분이 불필요한 것인지 이해하지 못했습니다. "with"문을 사용하여 파일을 열지 않으면 close()를 사용할 필요가 없습니까? – user3466240

+0

예. with 문을 컨텍스트 관리자로 사용하지 않으면 수동으로 파일 객체를 명시 적으로 닫아야합니다. 그러나'f.닫기 '를 선택하면 다시 닫을 때와 같이 문을 다시 열 때까지 무의미합니다. :피 –