3 Updating
Matthias Mailänder редактировал(а) эту страницу 2015-08-02 14:07:46 +02:00

How to use SharpZipLib to update Zip files

This page shows how to update an existing zip file. Contents may be added, overwritten or deleted.

Basic updating of a zip file

First example shows how to add or overwrite entries in a zip file on disk. This concentrates on the essentials.

Please note for AES: this will not work in the 0.86.0 release, if the existing zip has entries encrypted with AES. In that case you will need to repack into a new zip - see the Unpack and Repack sample at Zip Code Samples - creating and extracting

using ICSharpCode.SharpZipLib.Zip;

public void UpdateExistingZip() {
	ZipFile zipFile = new ZipFile(@"c:\temp\existing.zip");

	// Must call BeginUpdate to start, and CommitUpdate at the end.
	zipFile.BeginUpdate();

	zipFile.Password = "whatever"; // Only if a password is wanted on the new entry

	// The "Add()" method will add or overwrite as necessary.
	// When the optional entryName parameter is omitted, the entry will be named
	// with the full folder path and without the drive e.g. "temp/folder/test1.txt".
	//
	zipFile.Add(@"c:\temp\folder\test1.txt");

	// Specify the entryName parameter to modify the name as it appears in the zip.
	//
	zipFile.Add(@"c:\temp\folder\test2.txt", "test2.txt");

	// Continue calling .Add until finished.

	// Both CommitUpdate and Close must be called.
	zipFile.CommitUpdate();
	zipFile.Close();
}

Updating a zip file in memory

This example uses streams for both the zip and the entry to be added/updated.

  1. When the zip is a memorystream, this is no different to updating a zip on disk, except you need to set IsStreamOwner false to avoid the memorystream being automatically closed.
  2. When the entry is in a memorystream, you must use an implementation of IStaticDataSource to provide the stream to the Zipfile.Add method. As the example shows, this is straightforward.
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;

/// <summary>
/// Updates a zip file (in a disk or memorystream) adding the entry contained in the second stream.
/// </summary>
/// <param name="zipStream">Zip file, could be a disk or memory stream. Must be seekable. </param>
/// <param name="entryStream">Stream containing a file to be added. </param>
/// <param name="entryName">Name to appear in the zip entry. </param>
/// 
public void UpdateZipInMemory(Stream zipStream, Stream entryStream, String entryName) {

    // The zipStream is expected to contain the complete zipfile to be updated
    ZipFile zipFile = new ZipFile(zipStream);

    zipFile.BeginUpdate();

    // To use the entryStream as a file to be added to the zip,
    // we need to put it into an implementation of IStaticDataSource.
    CustomStaticDataSource sds = new CustomStaticDataSource();
    sds.SetStream(entryStream);

    // If an entry of the same name already exists, it will be overwritten; otherwise added.
    zipFile.Add(sds, entryName);

    // Both CommitUpdate and Close must be called.
    zipFile.CommitUpdate();
    // Set this so that Close does not close the memorystream
    zipFile.IsStreamOwner = false;
    zipFile.Close();

    // Reposition to the start for the convenience of the caller.
    zipStream.Position = 0;
}

public class CustomStaticDataSource : IStaticDataSource {
    private Stream _stream;
    // Implement method from IStaticDataSource
    public Stream GetSource() {
        return _stream;
    }

    // Call this to provide the memorystream
    public void SetStream(Stream inputStream) {
        _stream = inputStream;
        _stream.Position = 0;
    }
}

// This test harness CallingExample method illustrates the use of the UpdateZipInMemory method above.
// In this example, we copy a zip file from disk into a memorystream, update it, and write the memorystream back to
// a (different) disk file. Note that the UpdateZipInMemory method parameters are Stream - any stream will do,
// it does not have to be a memorystream. The zipStream must be seekable, but the entryStream need not.
//
public void CallingExample() {

    // Read a disk file into memory
    MemoryStream msZip = new MemoryStream();
    FileStream fs = File.OpenRead(@"c:\temp\existing.zip");

    // This utility method copies from stream to stream.
    // Using StreamUtils.Copy is more efficient than copying whole file into am intermediate byte array.
    byte[] buffer = new byte[4096];
    ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fs, msZip, buffer);
    fs.Close();

    // Create an entry to be added.
    FileStream fsEntry = File.OpenRead(@"c:\temp\test1.txt");
    MemoryStream msEntry = new MemoryStream();
    ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(fsEntry, msEntry, buffer);
    fsEntry.Close();

    // Do the update
    UpdateZipInMemory(msZip, msEntry, "test1updated.txt");

    // At this point, msZip contains the updated zip. We will write it to a new file.
    fs = File.Create(@"c:\temp\updated.zip");
    ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(msZip, fs, new byte[4096]);
    fs.Close();
}

Back to Code Reference main page