[Python-es] zipfile Buffered

Juan de Dios Manjón Pérez juande en jdmanjon.net
Mar Ene 25 01:12:47 CET 2011


Conseguido!!

A partir de esta información: 
http://stackoverflow.com/questions/297345/create-a-zip-file-from-a-generator-in-python/2734156#2734156

He creado esta implementación, os la dejo por si alguno le interesara:


import time, shutil
from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
import zlib, binascii, struct

class ZipWriter(object):
     def __init__(self, zf, filename):
         self.zf = zf
         self.filename = filename
         self.zinfo = self._ZipInfo(filename)
         self.file_size = 0
         self.compress_size = 0
         self.CRC = 0

         if self.zinfo.compress_type == ZIP_DEFLATED:
             self.cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, 
zlib.DEFLATED, -15)
         else:
             self.cmpr = None

     def _ZipInfo(self, filename):
         zinfo = ZipInfo(filename=filename,
                             date_time=time.localtime(time.time())[:6])
         zinfo.compress_type = self.zf.compression
         zinfo.external_attr = 0600 << 16
         zinfo.file_size = 0
         zinfo.flag_bits = 0x00
         zinfo.CRC = 0
         zinfo.compress_size = 0

         zinfo.header_offset = self.zf.fp.tell()    # Start of header bytes

         self.zf._writecheck(zinfo)
         self.zf._didModify = True

         self.zf.fp.write(zinfo.FileHeader())

         return zinfo

     def write(self, bytes):
         self.file_size = self.file_size + len(bytes)
         self.CRC = binascii.crc32(bytes, self.CRC)
         if self.cmpr:
             bytes = self.cmpr.compress(bytes)
             self.compress_size = self.compress_size + len(bytes)

         self.zf.fp.write(bytes)

     def close(self):
         if self.cmpr:
             buf = cmpr.flush()
             self.compress_size = self.compress_size + len(buf)
             self.zf.fp.write(buf)
             self.zinfo.compress_size = self.compress_size
         else:
             self.zinfo.compress_size = self.file_size

         self.zinfo.CRC = self.CRC
         self.zinfo.file_size = self.file_size

         position = self.zf.fp.tell()
         self.zf.fp.seek(self.zinfo.header_offset + 14, 0)
         self.zf.fp.write(struct.pack("<lLL", self.zinfo.CRC, 
self.zinfo.compress_size, self.zinfo.file_size))
         self.zf.fp.seek(position, 0)
         self.zf.filelist.append(self.zinfo)
         self.zf.NameToInfo[self.zinfo.filename] = self.zinfo

def copyZipFile(source, target):
     zsource = ZipFile(source, "r")
     ztarget = ZipFile(target, "w")

     for item in zsource.infolist():
         fsrc = zsource.open(item.filename, "r")
         fdst = ZipWriter(ztarget, item.filename)
         shutil.copyfileobj(fsrc, fdst)
         fdst.close()
         fsrc.close()

     zsource.close()
     ztarget.close()



Saludos

Juande







El 24/01/2011 23:29, Juan de Dios Manjón Pérez escribió:
> Andrey,
>
> también he llegado al punto que comentas,
> el problema que tengo ahora es para escribir el chuck, ya que 
> ZipFile.open(name, mode='r', pwd=None) no admite mode='w'.
>
> El unico metodo ZipFile.writestr(zinfo_or_arcname, bytes) que he 
> encontrado para escribir requiere que se escriba TODO de golpe.
>
> La implementación que busco es parecida a:
>
> from zipfile import ZipFile
> from shutil import copyfileobj
>
> def copyZipFile(source, target):
>     zsource = ZipFile(source,"r")
>     ztarget = ZipFile(target,"w")
>
>     for item in zsource.infolist():
>         fsrc = zsource.open(item.filename,"r")
>         fdst = ztarget.open(item.filename,"w") #mode no acepta "w". 
> exception
>         copyfileobj(fsrc,fdst)
>         fdst.close()
>         fsrc.close()
>
>     zsource.close()
>     ztarget.close()
>
>
> Saludos
>
> Juande
>
>
>
> El 24/01/2011 20:14, Andrey Antoukh escribió:
>> http://docs.python.org/py3k/library/zipfile.html
>>
>> ZipFile.open(name, mode='r', pwd=None)
>> Extract a member from the archive as a file-like object (ZipExtFile). 
>> name is the name of the file in the archive, or a ZipInfo object. The 
>> mode parameter, if included, must be one of the following: 'r' (the 
>> default), 'U', or 'rU'. Choosing 'U' or 'rU' will enable universal 
>> newline support in the read-only object. pwd is the password used for 
>> encrypted files. Calling open() on a closed ZipFile will raise a 
>> RuntimeError.
>>
>> Note The file-like object is read-only and provides the following 
>> methods: read(), readline(), readlines(), __iter__(), __next__().
>>
>> Lo que a groso modo quiere decir que devuelve un objeto fichero que 
>> tiene todos los métodos estándares para leer. De lo que se deduce que 
>> podemos leerlos a cachitos para que no ocupe memoria.
>>
>> La implementación seria parecida a la que ya se ha propuesto.  O como 
>> el simple ejemplo...
>>
>> >>> zipobj = zipfile.ZipFile("prueba.zip", "r")
>> >>> for zip in zipobj.namelist():
>> ...     zipfileobj = zipobj.open(zip, "r")
>> ...     for chuck in zipfileobj:
>> ...         # lo que sea que tengas que hacer con estos datos.
>>
>> Un saludo.
>
>
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> http://mail.python.org/mailman/listinfo/python-es
> FAQ: http://python-es-faq.wikidot.com/

------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20110125/d64de70f/attachment.html>


Más información sobre la lista de distribución Python-es