2014-03-26 38 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的子类来处理它,但我相信可能有更好的方法。

我使用Python 2.7

预先感谢您的任何建议!

+1

您的解决方案有什么问题?我不会关闭文件,然后立即重新打开它,但用try/except处理潜在的IOError是完全正确的。只是尝试读取它作为gzip,除了'IOError'读作纯文本,除了'IOError'回溯。然后干净地处理所有的处理,处理代码不知道文件是如何打开的。 –

+0

那么,我的解决方案可能没有什么问题(我对Python的经验并不丰富,有时候我怀疑什么是好的/错误的)。我不喜欢我的解决方案的原因是我至少会编写6个解码函数(针对6种不同的文件类型),我认为可能有更好的方法可以避免在每个函数中写入try-except块。但感谢您的评论。 – user3466240

+0

如果问题是您不想复制代码,那么只需创建一个新的上下文管理器,无论输入是否压缩,都会生成一个具有未压缩数据的文件类对象。下面是一个[上下文管理器'named_pipe()'的代码示例,它封装了创建命名管道](http://stackoverflow.com/a/22435492/4279) – jfs

回答

1

可以检查头两个字节是\x1f\x8b,按照RFC 1952

会员首部和尾部

ID1(识别1)ID2(识别2) 这些具有固定值ID1 = 31(0x1f,\ 037),ID2 = 139(0x8b,\ 213),以标识文件为gzip格式。

因此,例如,

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

感谢您的回答。 (我对两位炼金术士的评论也适用于此)。但我不明白我的代码的哪一部分是不必要的:如果我不使用“with”语句打开文件,是否需要使用close()? – user3466240

+0

是的,如果不使用with语句作为上下文管理器,应该尝试手动显式关闭文件对象。但是,写'f。关闭“,然后”打开(same_file)“与关闭然后重新打开即将退出的门无关。 :P –

相关问题