将zip解压缩到内存,解析内容

时间:2014-05-09 16:29:18

标签: python zipfile stringio

我想将zip文件的内容读入内存而不是将它们提取到光盘,在存档中查找特定文件,打开文件并从中提取一行。

可以打开并解析StringIO实例吗?建议?提前谢谢。

zfile = ZipFile('name.zip', 'r')

    for name in zfile.namelist():
        if fnmatch.fnmatch(name, '*_readme.xml'):
            name = StringIO.StringIO()
            print name # prints StringIO instances
            open(name, 'r')  # IO Error: No such file or directory...

我发现了一些类似的帖子,但似乎都没有解决这个问题:Extracting a zipfile to memory?

4 个答案:

答案 0 :(得分:4)

刚刚使用read的IMO就足够了:

zfile = ZipFile('name.zip', 'r')
files = []
for name in zfile.namelist():
  if fnmatch.fnmatch(name, '*_readme.xml'):
    files.append(zfile.read(name))

这将生成一个包含数学模式文件内容的列表。

测试: 然后,您可以通过迭代列表来解析病房后的内容:

for file in files:
  print(file[0:min(35,len(file))].decode()) # "parsing"

或者更好地使用仿函数:

import zipfile as zip
import os
import fnmatch

zip_name = os.sys.argv[1]
zfile = zip.ZipFile(zip_name, 'r')

def parse(contents, member_name = ""):
  if len(member_name) > 0:
    print( "Parsed `{}`:".format(member_name) )  
  print(contents[0:min(35, len(contents))].decode()) # "parsing"

for name in zfile.namelist():
  if fnmatch.fnmatch(name, '*.cpp'):
    parse(zfile.read(name), name)

这样就没有任何原因在内存中保留数据,并且内存占用较小。如果文件很大,这可能很重要。

答案 1 :(得分:1)

您链接的问题表明您需要阅读该文件。取决于您的用例可能已经足够了。在您的代码中,您将带有空字符串缓冲区的文件名替换为循环变量。尝试这样的事情:

zfile = ZipFile('name.zip', 'r')

for name in zfile.namelist():
    if fnmatch.fnmatch(name, '*_readme.xml'):
        ex_file = zfile.open(name) # this is a file like object
        content = ex_file.read() # now file-contents are a single string

如果你真的想要一个可以操作的缓冲区,那么只需用内容实例化它:

buf = StringIO(zfile.open(name).read())

您可能还想查看BytesIO并注意Python 2和3之间存在差异。

答案 2 :(得分:1)

不要过分思考它。它只是工作:

import zipfile

# 1) I want to read the contents of a zip file ...
with zipfile.ZipFile('A-Zip-File.zip') as zipper:
  # 2) ... find a particular file in the archive, open the file ...
  with zipper.open('A-Particular-File.txt') as fp:
    # 3) ... and extract a line from it.
    first_line = fp.readline()

print first_line

答案 3 :(得分:0)

感谢所有提供解决方案的人。这就是最终为我工作的原因:

zfile = ZipFile('name.zip', 'r')

        for name in zfile.namelist():
            if fnmatch.fnmatch(name, '*_readme.xml'):
                zopen = zfile.open(name)
                for line in zopen:
                    if re.match('(.*)<foo>(.*)</foo>(.*)', line):
                        print line