我想從壓縮文件中提取文件到特定路徑,忽略存檔中的文件路徑。這是在Python 2.6非常簡單(我的文檔字符串比代碼更長)如何在Python 2.5中模擬ZipFile.open?
import shutil
import zipfile
def extract_from_zip(name, dest_path, zip_file):
"""Similar to zipfile.ZipFile.extract but extracts the file given by name
from the zip_file (instance of zipfile.ZipFile) to the given dest_path
*ignoring* the filename path given in the archive completely
instead of preserving it as extract does.
"""
dest_file = open(dest_path, 'wb')
archived_file = zip_file.open(name)
shutil.copyfileobj(archived_file, dest_file)
extract_from_zip('path/to/file.dat', 'output.txt', zipfile.ZipFile('test.zip', 'r'))
但是在Python 2.5,該ZipFile.open方法不可用。我找不到在stackoverflow上的解決方案,但this forum post有一個很好的解決方案,它使用ZipInfo.file_offset
來尋找zip中的正確點,並使用zlib.decompressobj
來從那裏解壓字節。不幸的是ZipInfo.file_offset
在Python 2.5中被刪除了!
因此,鑑於我們在Python 2.5中的所有內容都是ZipInfo.header_offset
,我想我只需要解析並跳過頭結構以自己到達文件偏移量。使用維基百科作爲a reference(我知道)我想出了這個更長,不是很優雅的解決方案。
import zipfile
import zlib
def extract_from_zip(name, dest_path, zip_file):
"""Python 2.5 version :("""
dest_file = open(dest_path, 'wb')
info = zip_file.getinfo(name)
if info.compress_type == zipfile.ZIP_STORED:
decoder = None
elif info.compress_type == zipfile.ZIP_DEFLATED:
decoder = zlib.decompressobj(-zlib.MAX_WBITS)
else:
raise zipfile.BadZipFile("Unrecognized compression method")
# Seek over the fixed size fields to the "file name length" field in
# the file header (26 bytes). Unpack this and the "extra field length"
# field ourselves as info.extra doesn't seem to be the correct length.
zip_file.fp.seek(info.header_offset + 26)
file_name_len, extra_len = struct.unpack("<HH", zip_file.fp.read(4))
zip_file.fp.seek(info.header_offset + 30 + file_name_len + extra_len)
bytes_to_read = info.compress_size
while True:
buff = zip_file.fp.read(min(bytes_to_read, 102400))
if not buff:
break
bytes_to_read -= len(buff)
if decoder:
buff = decoder.decompress(buff)
dest_file.write(buff)
if decoder:
dest_file.write(decoder.decompress('Z'))
dest_file.write(decoder.flush())
注我怎樣解包和讀,賦予額外的字段的長度的字段中,因爲在屬性ZipInfo.extra
主叫len
給出4個字節以下,從而使所述偏移被錯誤地計算。也許我在這裏錯過了一些東西?
任何人都可以改進此解決方案爲Python 2.5?
編輯:我應該說,顯而易見的解決辦法的建議通過ChrisAdams因爲它試圖發出聲音整個文件到內存
dest_file.write(zip_file.read(name))
將失敗,並MemoryError
爲包含在ZIP任何合理大小的文件一氣呵成。我有大文件,所以我需要將內容流出到磁盤。另外,升級Python是顯而易見的解決方案,但是完全不在我的手中,實際上不可能。
你爲什麼不能升級?2.7是最新的t他2.x系列,你很過時......沒有理由留在舊版 – Daenyth 2010-09-23 18:22:36
@Daenyth我只希望。嘗試告訴負責管理x00服務器的操作團隊... – Day 2010-09-23 20:46:19