Python:从二进制文件而不是文件名打开 zip 文件

Posted

技术标签:

【中文标题】Python:从二进制文件而不是文件名打开 zip 文件【英文标题】:Python: Open zip file from binary instead of filename 【发布时间】:2013-09-23 18:52:29 【问题描述】:

有没有办法通过传入 zip 文件的文字字节来初始化 ZipFile 对象,而不是让它读取文件名?我正在构建一个不需要触摸磁盘的宁静应用程序;它只是打开文件,对其进行处理,重新压缩并发送。

【问题讨论】:

明确一点:我想要的是能够从二进制字符串打开 zip 文件。如,我传入一个包含二进制数据的字符串,然后我收到一个 ZipFile 对象。到目前为止,我看到的 StringIO 代码处理将 ZipFile 写入字符串,但它似乎没有提供避免写入临时文件的方法。 【参考方案1】:

在其他答案的 cmets 中,你说你想这样做:

打开一个二进制字符串,就像它是一个 zip 文件一样。打开它,读/写里面的文件,然后关闭它

您只需执行与其他答案相同的操作,只是创建一个预先填充了二进制字符串的StringIO.StringIO(或cStringIO.StringIOio.BytesIO),并在最后提取该字符串。 StringIO 和朋友为他们的构造函数获取一个可选的初始字符串,并在完成后使用getvalue 方法来提取字符串。 The documentation很简单,值得一读。

所以,尽可能地接近 alecxe 的答案:

from zipfile import ZipFile
try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

in_memory = StringIO.StringIO(original_zip_data)
zf = ZipFile(in_memory, "a")  

zf.writestr("file.txt", "some text contents")

zf.close()

new_zip_data = in_memory.getvalue()

但是,请注意ZipFile 不能真正就地写入 zip 存档,除非是向其附加新文件的特殊情况。这对于内存中的 zip 存档和磁盘上的存档一样正确。您通常可以通过附加具有相同路径的新文件来避免覆盖存档中的文件,但这通常是一个坏主意(尤其是如果您要创建这些内容以通过 Internet 发送)。

因此,您可能想要做的与您想要修改文件时完全相同:创建一个单独的输出文件,从输入文件中复制您需要的内容,然后在进行过程中编写新内容。只是在这种情况下,输入和输出文件都是ZipFile对象包裹StringIO对象。

【讨论】:

【参考方案2】:

这是一个使用(c)StringIO的示例:

from zipfile import ZipFile
try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

in_memory = StringIO.StringIO()   
zf = ZipFile(in_memory, "a")  

zf.writestr("file.txt", "some text contents")

zf.close()

另见:

Function to create in-memory zip file and return as http response How can I pass a Python StringIO() object to a ZipFile(), or is it not supported? Django zip files (create dynamic in-memory archives with Python's zipfile)

【讨论】:

BytesIO 不是更好吗?特别是因为代码将在 2 和 3 之间移植。【参考方案3】:

当然,使用 (c)StringIO 代替:http://docs.python.org/2/library/stringio.html 此外,您应该为 Python 3 使用 BytesIO。不过,它确实存在于 2.6 和 2.7 中。

【讨论】:

我想你的意思是BytesIO,但是是的。 @Marcin:在 Python 2.x 中,StringIO.StringIO 很好。在 3.x 中,是的,您可能想改用 io.BytesIO @abarnert 对。所以使用StringIO 只是无缘无故地引入了可移植性问题。 @Marcin: 当然,但是使用BytesIO 也会引入一个可移植性问题,因为它在 Python 2.5 中不存在(并且,IIRC,比之前的 StringIO/cStringIO 慢得多2.7.2 左右……但我可能记错了,而且不太重要)。换一种说法:您是否认为应该在 2.x 中始终使用 io.open 而不是 open 用于普通文件? @abarnert 在这一点上,几乎可以,除非已知需要 2.7 之前的兼容性。我们现在已经 3 年进入 2.7 作为当前版本系列。任何人都没有理由使用 2.6。 (我不认为您的发行版安装了过期版本是一个很好的理由)。

以上是关于Python:从二进制文件而不是文件名打开 zip 文件的主要内容,如果未能解决你的问题,请参考以下文章

在python中如何从二进制文件中读取信息

用python从二进制文件中读取32位带符号的ieee 754浮点?

从二进制数据流中构造GDAL能够读取的图像数据

如何从二进制文件中读取块并使用 Python 或 Perl 解包提取结构?

将核心数据文件从二进制转换为 XML

Dask 从二进制文件中读取数据