2

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.

shantanuo
  • 31,689
  • 78
  • 245
  • 403

1 Answers1

1

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
Alderven
  • 7,569
  • 5
  • 26
  • 38
  • This solution is correct. But it also changes the ownership of the new file. For e.g. now the owner is "root" instead of "ubuntu". Is it possible to update zip file without changing the ownership? I can use chown command but what if I don't know the original owner? – shantanuo Aug 04 '23 at 08:28