diff -r e1be927146df Lib/zipfile.py --- a/Lib/zipfile.py Sat Dec 13 05:02:20 2008 +0100 +++ b/Lib/zipfile.py Sat Dec 13 20:31:35 2008 +0100 @@ -2,7 +2,12 @@ Read and write ZIP files. """ import struct, os, time, sys, shutil -import binascii, cStringIO +import binascii + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO try: import zlib # We may need its compression method @@ -451,7 +456,8 @@ class ZipExtFile: self.decrypter = decrypt self.bytes_read = 0L self.rawbuffer = '' - self.readbuffer = '' + self.readbuffer = StringIO() + self.readbufferlength = 0 self.linebuffer = '' self.eof = False self.univ_newlines = False @@ -468,7 +474,7 @@ class ZipExtFile: # read from compressed files in 64k blocks self.compreadsize = 64*1024 if self.compress_type == ZIP_DEFLATED: - self.dc = zlib.decompressobj(-15) + self.dc = zlib.decompressobj(-zlib.MAX_WBITS) def set_univ_newlines(self, univ_newlines): self.univ_newlines = univ_newlines @@ -578,10 +584,10 @@ class ZipExtFile: if size is not None and size >= 0: if self.compress_type == ZIP_STORED: - lr = len(self.readbuffer) + lr = self.readbufferlength - self.readbuffer.tell() bytesToRead = min(bytesToRead, size - lr) elif self.compress_type == ZIP_DEFLATED: - if len(self.readbuffer) > size: + if self.readbufferlength - self.readbuffer.tell() > size: # the user has requested fewer bytes than we've already # pulled through the decompressor; don't read any more bytesToRead = 0 @@ -603,7 +609,6 @@ class ZipExtFile: # handle contents of raw buffer if self.rawbuffer: newdata = self.rawbuffer - self.rawbuffer = '' # decrypt new data if we were given an object to handle that if newdata and self.decrypter is not None: @@ -620,20 +625,16 @@ class ZipExtFile: newdata += self.dc.flush() # prevent decompressor from being used again self.dc = None + else: + self.rawbuffer = '' - self.readbuffer += newdata - + newdata = self.readbuffer.read() + newdata + # reallocate a new StringIO in order to avoid memory growth + self.readbuffer = StringIO(newdata) + self.readbufferlength = len(newdata) # return what the user asked for - if size is None or len(self.readbuffer) <= size: - bytes = self.readbuffer - self.readbuffer = '' - else: - bytes = self.readbuffer[:size] - self.readbuffer = self.readbuffer[size:] - - return bytes - + return self.readbuffer.read(size or -1) class ZipFile: """ Class with methods to open, read, write, close, list zip files. @@ -747,7 +748,7 @@ class ZipFile: self.start_dir = offset_cd + concat fp.seek(self.start_dir, 0) data = fp.read(size_cd) - fp = cStringIO.StringIO(data) + fp = StringIO(data) total = 0 while total < size_cd: centdir = fp.read(sizeCentralDir) @@ -1347,18 +1348,7 @@ def main(args = None): zf = ZipFile(args[1], 'r') out = args[2] - for path in zf.namelist(): - if path.startswith('./'): - tgt = os.path.join(out, path[2:]) - else: - tgt = os.path.join(out, path) - - tgtdir = os.path.dirname(tgt) - if not os.path.exists(tgtdir): - os.makedirs(tgtdir) - fp = open(tgt, 'wb') - fp.write(zf.read(path)) - fp.close() + zf.extractall(out) zf.close() elif args[0] == '-c':