压缩文件可分为以下逻辑组
a.你正在使用的操作系统(*ix,Win)等等。
b.不同类型的压缩算法(即.zip、.Z、.bz2、.rar、.gzip)。至少从最常用的压缩文件的标准列表。
c.然后我们有了焦油球机制--我想没有压缩。但它的行为更像是一种串联。
现在,如果我们开始处理上述一组压缩文件,
a.选项(a)将由python处理,因为它是独立于平台的语言。
b.方案(b)和(c)似乎有问题。
我需要什么
如何识别文件类型(压缩类型),然后解压缩?
像这样:
fileType = getFileType(fileName)
switch(fileType):
case .rar: unrar....
case .zip: unzip....
etc
所以最基本的问题是我们如何识别基于文件的压缩算法(假设没有提供扩展名或扩展名不正确)?在python中有什么特别的方法吗?
发布于 2012-10-24 07:53:39
This page有一个“神奇”文件签名列表。把你需要的东西放在字典里,如下所示。然后我们需要一个函数来匹配dict键和文件的开头。我已经写了一个建议,尽管它可以通过将magic_dict
预处理成一个巨大的编译正则表达式来进行优化。
magic_dict = {
"\x1f\x8b\x08": "gz",
"\x42\x5a\x68": "bz2",
"\x50\x4b\x03\x04": "zip"
}
max_len = max(len(x) for x in magic_dict)
def file_type(filename):
with open(filename) as f:
file_start = f.read(max_len)
for magic, filetype in magic_dict.items():
if file_start.startswith(magic):
return filetype
return "no match"
这个解决方案应该是跨平台的,当然不依赖于文件扩展名,但它可能会给带有随机内容的文件带来误报,这些随机内容恰好是以一些特定的魔术字节开始的。
发布于 2012-10-24 08:57:43
基于lazyr的回答和我的评论,我的意思是:
class CompressedFile (object):
magic = None
file_type = None
mime_type = None
proper_extension = None
def __init__(self, f):
# f is an open file or file like object
self.f = f
self.accessor = self.open()
@classmethod
def is_magic(self, data):
return data.startswith(self.magic)
def open(self):
return None
import zipfile
class ZIPFile (CompressedFile):
magic = '\x50\x4b\x03\x04'
file_type = 'zip'
mime_type = 'compressed/zip'
def open(self):
return zipfile.ZipFile(self.f)
import bz2
class BZ2File (CompressedFile):
magic = '\x42\x5a\x68'
file_type = 'bz2'
mime_type = 'compressed/bz2'
def open(self):
return bz2.BZ2File(self.f)
import gzip
class GZFile (CompressedFile):
magic = '\x1f\x8b\x08'
file_type = 'gz'
mime_type = 'compressed/gz'
def open(self):
return gzip.GzipFile(self.f)
# factory function to create a suitable instance for accessing files
def get_compressed_file(filename):
with file(filename, 'rb') as f:
start_of_file = f.read(1024)
f.seek(0)
for cls in (ZIPFile, BZ2File, GZFile):
if cls.is_magic(start_of_file):
return cls(f)
return None
filename='test.zip'
cf = get_compressed_file(filename)
if cf is not None:
print filename, 'is a', cf.mime_type, 'file'
print cf.accessor
现在可以使用cf.accessor
访问压缩数据。所有的模块都提供了类似的方法,比如'read()','write()‘等等。
发布于 2012-10-24 07:32:37
这是一个复杂的问题,取决于许多因素:最重要的是您的解决方案需要多大的可移植性。
在给定文件的情况下,查找文件类型的基本方法是在文件中查找标识标头,通常称为"magic sequence" or signature header,它标识文件属于某种类型。如果可以避免,通常不会使用它的名称或扩展名。对于某些文件,Python内置了此功能。例如,要处理.tar
文件,可以使用tarfile
模块,它有一个方便的is_tarfile
方法。还有一个类似的模块,名为zipfile
。这些模块还允许您使用纯Python提取文件。
例如:
f = file('myfile','r')
if zipfile.is_zipfile(f):
zip = zipfile.ZipFile(f)
zip.extractall('/dest/dir')
elif tarfile.is_tarfile(f):
...
如果您的解决方案仅适用于Linux或OSX,也可以使用file
命令,它将为您完成大量工作。您还可以使用内置工具来解压缩文件。如果你只是在做一个简单的脚本,这个方法会更简单,会给你带来更好的性能。
https://stackoverflow.com/questions/13044562
复制相似问题