Updating - icsharpcode/SharpZipLib GitHub Wiki
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.
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();
}
This example uses streams for both the zip and the entry to be added/updated.
- 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.
- 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();
}