pythonpython-zipfile

not able to append a zip file


I have this function that is working and replacing the content from a given file.

import os
import zipfile
import tempfile

def updateZip(zipname, filename, data):
    # generate a temp file
    tmpfd, tmpname = tempfile.mkstemp(dir=os.path.dirname(zipname))
    os.close(tmpfd)

    # create a temp copy of the archive without filename            
    with zipfile.ZipFile(zipname, 'r') as zin:
        with zipfile.ZipFile(tmpname, 'w') as zout:
            zout.comment = zin.comment # preserve the comment
            for item in zin.infolist():
                if item.filename != filename:
                    zout.writestr(item, zin.read(item.filename))

    # replace with the temp archive
    os.remove(zipname)
    os.rename(tmpname, zipname)

    # now add filename with its new data
    with zipfile.ZipFile(zipname, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
        zf.writestr(filename, data)

If I call the function twice as shown below, then the text in the file is "second note".

updateZip('acor_en-US.dat', 'DocumentList.xml', 'first note')

updateZip('acor_en-US.dat', 'DocumentList.xml', 'second note')

But I need "first note" and "second note" in that file. In other words I am not able to append a zip file.


Solution

  • You need to read data from the file before rewriting it:

    import io
    import os
    import zipfile
    import tempfile
    
    
    def updateZip(zipname, filename, data):
        # generate a temp file
        tmpfd, tmpname = tempfile.mkstemp(dir=os.path.dirname(zipname))
        os.close(tmpfd)
    
        # read data from file
        with zipfile.ZipFile(zipname) as zf:
            with io.TextIOWrapper(zf.open(filename), encoding='utf-8') as f:
                data = f.read() + data
    
        # create a temp copy of the archive without filename
        with zipfile.ZipFile(zipname, 'r') as zin:
            with zipfile.ZipFile(tmpname, 'w') as zout:
                zout.comment = zin.comment  # preserve the comment
                for item in zin.infolist():
                    if item.filename != filename:
                        zout.writestr(item, zin.read(item.filename))
    
        # replace with the temp archive
        os.remove(zipname)
        os.rename(tmpname, zipname)
    
        # now add filename with its new data
        with zipfile.ZipFile(zipname, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            zf.writestr(filename, data)
    
    
    updateZip('acor_en-US.dat', 'DocumentList.xml', 'first note')
    updateZip('acor_en-US.dat', 'DocumentList.xml', 'second note')
    

    Content of the DocumentList.xml:

    first notesecond note