2013-09-23 149 views
2

有什麼辦法通過傳遞zip文件的字面字節來初始化一個ZipFile對象,而不是讓它讀取文件名?我正在構建一個不需要永遠接觸磁盤的寧靜應用程序;它只是打開文件,做一些工作,重新壓縮併發送它。Python:從二進制打開zip文件而不是文件名

+0

只是要清楚:我想要的是能夠打開一個二進制字符串的zip文件。在中,我傳遞一個包含二進制數據的字符串,並且收到一個ZipFile對象。到目前爲止,我見過的StringIO代碼涉及將ZipFile編寫成字符串,但似乎沒有提供避免寫入臨時文件的方法。 –

回答

4

在對其他答案的評論中,你說你想這麼做:

打開一個二進制字符串,就好像它是一個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來代替:http://docs.python.org/2/library/stringio.html 另外,您應該使用BytesIO for Python 3.它確實存在於2.6和2.7中。

+0

我認爲你的意思是'BytesIO',但是。 – Marcin

+1

@Marcin:在Python 2.x中,'StringIO.StringIO'很好。在3.x中,是的,你應該使用'io.BytesIO'來代替。 – abarnert

+0

@abarnert對。所以使用'StringIO'只是無緣無故地引入了可移植性問題。 – Marcin

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() 

另見:

+0

BytesIO會不會更好?特別是因爲代碼將在2到3之間便攜。 – Marcin