将zip提取到内存中,解析内容

2 投票
4 回答
12140 浏览
提问于 2025-04-18 06:01

我想把一个压缩文件的内容直接读到内存里,而不是先解压到硬盘上,然后在这个压缩包里找到一个特定的文件,打开它并提取其中的一行。

请问可以打开和解析一个 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...

我找到了一些类似的帖子,但没有一个能解决这个问题: 如何将压缩文件提取到内存中?

4 个回答

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之间的区别。

3

别想太多,直接用就行:

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
4

我觉得只用 read 就够了:

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

感谢所有提供解决方案的人。这是我最终找到的有效方法:

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

撰写回答