2008-12-03 23 views
15

Sử dụng python 2.4 và thư viện được xây dựng trong ZipFile, tôi không thể đọc tệp zip rất lớn (lớn hơn 1 hoặc 2 GB) vì nó muốn lưu trữ toàn bộ nội dung của tệp không nén trong bộ nhớ. Có một cách khác để làm điều này (hoặc với một thư viện của bên thứ ba hoặc một số hack khác), hoặc tôi phải "bóc vỏ" và giải nén nó theo cách đó (mà không phải là nền tảng, rõ ràng).Làm thế nào để bạn giải nén các tệp rất lớn trong python?

Trả lời

16

Dưới đây là một phác thảo giải nén các tệp lớn.

import zipfile 
import zlib 
import os 

src = open(doc, "rb") 
zf = zipfile.ZipFile(src) 
for m in zf.infolist(): 

    # Examine the header 
    print m.filename, m.header_offset, m.compress_size, repr(m.extra), repr(m.comment) 
    src.seek(m.header_offset) 
    src.read(30) # Good to use struct to unpack this. 
    nm= src.read(len(m.filename)) 
    if len(m.extra) > 0: ex= src.read(len(m.extra)) 
    if len(m.comment) > 0: cm= src.read(len(m.comment)) 

    # Build a decompression object 
    decomp= zlib.decompressobj(-15) 

    # This can be done with a loop reading blocks 
    out= open(m.filename, "wb") 
    result= decomp.decompress(src.read(m.compress_size)) 
    out.write(result) 
    result = decomp.flush() 
    out.write(result) 
    # end of the loop 
    out.close() 

zf.close() 
src.close() 
+0

Đây chính xác là những gì tôi đang tìm kiếm - cảm ơn! –

+1

@ s-lott 'ex = src.read (len (m.extra))' và 'cm = src.read (len (m.comment))' bạn sử dụng các biến 'ex' và' cm là gì? 'cho? Bạn có ý nghĩa gì khi sử dụng cấu trúc để giải nén này? Và số ma thuật '30' được sử dụng để làm gì? – Jonathan

8

Tính đến Python 2.6, bạn có thể sử dụng ZipFile.open() để mở một tập tin xử lý trên một tập tin, và sao chép nội dung một cách hiệu quả vào một tập tin mục tiêu lựa chọn của bạn:

import errno 
import os 
import shutil 
import zipfile 

TARGETDIR = '/foo/bar/baz' 

with open(doc, "rb") as zipsrc: 
    zfile = zipfile.ZipFile(zipsrc) 
    for member in zfile.infolist(): 
     target_path = os.path.join(TARGETDIR, member.filename) 
     if target_path.endswith('/'): # folder entry, create 
      try: 
       os.makedirs(target_path) 
      except (OSError, IOError) as err: 
       # Windows may complain if the folders already exist 
       if err.errno != errno.EEXIST: 
        raise 
      continue 
     with open(target_path, 'wb') as outfile, zfile.open(member) as infile: 
      shutil.copyfileobj(infile, outfile) 

này sử dụng shutil.copyfileobj() để đọc một cách hiệu quả dữ liệu từ đối tượng zipfile mở, sao chép nó sang tệp đầu ra.

Các vấn đề liên quan