Zip Code Example: Compress and Decompress to and from memory

An example of how to use the Zip component with streams to perform operations in memory.

Date Entered: 05/30/2008    Last Updated: 01/13/2014

The components can be used to perform in-memory operations. This allows you to create or extract zip files without touching the disk.

Java and .NET

When compressing you may specify an InputStream for the files added to the collection either via the use of the constructor, or via the InputStream field. If you do not want the stream to be closed once the operation is complete you may set the CloseStreamAfterCompress configuration setting. For instance:

C#
MemoryStream file1 = new MemoryStream(Encoding.ASCII.GetBytes("Test 1"));
MemoryStream file2 = new MemoryStream(Encoding.ASCII.GetBytes("Test 2"));
MemoryStream myStream = new MemoryStream();

zip.SetArchiveOutputStream(myStream);
zip.Files.Add(new ZIPFile("test1.txt",file1));
zip.Files.Add(new ZIPFile("test2.txt",file2));
	
//By setting this the output stream will not be closed when Compress completes
zip.Config("CloseStreamAfterCompress=false");
zip.Compress();

//You may then proceed to use the compressed data however you like. 
//Be sure to seek back to the beginning.
myStream.Seek(0,SeekOrigin.Begin);
Java
FileOutputStream output = new FileOutputStream("c:\\temp\\archive.zip");
zip.setArchiveOutputStream(output);
			
FileInputStream input = new FileInputStream ("c:\\test.txt");
			
zip.getFiles().add(new ipworkszip.ZIPFile());
zip.getFiles().item(0).setInputStream(input);
zip.getFiles().item(0).setCompressedName("test.txt");
			
zip.compress();

In order to extract in memory you must set the DecompressedName of all files in the Files collection to empty string. You must also tell the component to output the file data to the Progress event. You can then accumulate file data within the progress event and write to a stream or anything else you choose. For instance:

C#
MemoryStream myArchive = new MemoryStream(File.ReadAllBytes("c:\\test.zip"));
zip.SetArchiveInputStream(myArchive);
zip.OnProgress += new Zip.OnProgressHandler(zip_OnProgress);
zip.Config("WriteToProgressEvent=true");
zip.Scan();

//This is necessary so no files are actually written to disk.
foreach (ZIPFile file in zip.Files)
{
	file.DecompressedName = "";
}
zip.ExtractAll();
...

void zip_OnProgress(object sender, ZipProgressEventArgs e)
{
//Within the event you can examine e.FileName to determine the current file
//being extracted and examine e.Data to access the decompressed data.
}
Java
zip.setArchiveInputStream(new FileInputStream("c:\\temp\\archive.zip"));
zip.addZipEventListener(new DefaultZipEventListener(){
	public void progress(ZipProgressEvent e){
		System.out.println(e.filename + ": "+ (new String(e.data));
	}
});
			
zip.scan();
for(int i =0;i<zip.getFiles().size();i++)
{
	zip.getFiles().item(i).setDecompressedName("");
}

zip.config("WriteToProgressEvent=true");
zip.extractAll();

Note: By default, Password encryption is not allowed for archives created with WriteToProgressEvent set to true. You may set the EnableStreamingEncryption configuration setting to true in order to allow this, but streamed and encrypted zip files may be incompatible with other utilities.

Other Languages (C++, Delphi, ActiveX, etc.)

In editions of the toolkit which do not directly support streams, in-memory operations can be performed using a combination of properties and events. When compressing the archive data is available through the progress event. File data may be set using the FileInputData property.

Delphi

zip1.FileCount := 1;
zip1.FileInputDataB := my_file_data
zip1.Config('WriteToProgressEvent=True');
zip1.Compress();
...

procedure TFormOpenzip.Zip1Progress(Sender: TObject; Data: String;
  const Filename: String; BytesProcessed: Int64;
  PercentProcessed: Integer);
begin

  //The ProgressDataB property is valid only within this event and holds
  //the current archive or file data as a RawByteString.

  //To save the entire archive or file accumulate this data as the event
  //will fire multiple times
  
  //save the contents of Zip1.ProgressDataB
end;

Decompressing operates similarly to compressing. The archive data is specified in ZipData or ZipDataB and the decompressed file data is available through the Progress event. Before extracting the archive must first be scanned and FileDecompressedName set to empty string for each file to prevent extraction to disk.

Delphi

zip1.ZipDataB := my_archive_data;
zip1.Config('WriteToProgressEvent=True');
zip1.Scan();
for i := 0 to Zip1.FileCount - 1 do
begin
  zip1.FileDecompressedName[i] := '';
end;
zip1.ExtractAll();

procedure TFormOpenzip.Zip1Progress(Sender: TObject; Data: String;
  const Filename: String; BytesProcessed: Int64;
  PercentProcessed: Integer);
begin

  //The ProgressDataB property is valid only within this event and holds
  //the current archive or file data as a RawByteString.

  //To save the entire archive or file accumulate this data as the event
  //will fire multiple times

  //Check the Filename parameter to determine to which file the data is applicable
  
  //save the contents of Zip1.ProgressDataB
end;

We appreciate your feedback.  If you have any questions, comments, or suggestions about this entry please contact our support team at kb@nsoftware.com.