Using a generic stream to create a zipped file with SharpCompress #189

Closed
opened 2026-01-29 22:08:01 +00:00 by claunia · 3 comments
Owner

Originally created by @xavierpena on GitHub (Jun 1, 2017).

This is the only example that I've found that applies to writing to streams. I've tried to follow it and adapt it to my needs, but I am stuck at the exception it throws:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using SharpCompress.Common;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Writers;
using System;
using System.IO;

namespace DbManager.DjdbCore.Tests
{
	[TestClass]
	public class ZipTests
	{
		public ZipTests()
		{
			Directory.SetCurrentDirectory(AppContext.BaseDirectory);
		}

		[TestMethod]
		public void Test()
		{            
			var zip = File.OpenWrite(@"..\..\..\..\..\test-resources\zip_file_test.zip");
			var writerOptions = new WriterOptions(CompressionType.Deflate);
			var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions);            

			var memoryStream = new MemoryStream();            
			var binaryWriter = new BinaryWriter(memoryStream);
			binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw");

			var deflateStream = new DeflateStream(memoryStream, SharpCompress.Compressors.CompressionMode.Compress);
			deflateStream.Write(memoryStream.ToArray(), 0, Convert.ToInt32(memoryStream.Length));

			// EXCEPTION: SharpCompress.Compressors.Deflate.ZlibException: 'Cannot Read after Writing.'
			// Source code: if (_streamMode != StreamMode.Reader) { throw new ZlibException("Cannot Read after Writing."); }
			zipWriter.Write("test_file_inside_zip.bin", deflateStream, DateTime.Now);						  

			zip.Flush();

			zipWriter.Dispose();
			zip.Dispose();            
		}

	}
}

In case it helps, this is what I used (and it worked, but only in dotnet core) using the library System.IO.Compression:

private void WriteAsZipBinary()
{
	//Open the zip file if it exists, else create a new one 
	var zip = ZipPackage.Open(this.FileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);

	var zipStream = ZipManager.GetZipWriteStream(zip, nameOfFileInsideZip);

	var memoryStream = new MemoryStream();
	var binaryWriter = new BinaryWriter(memoryStream);
	
	// Here is where strings etc are written to the binary file:
	WriteStuffInBinaryStream(ref binaryWriter);

	//Read all of the bytes from the file to add to the zip file 
	byte[] bites = new byte[Convert.ToInt32(memoryStream.Length - 1) + 1];
	memoryStream.Position = 0;
	memoryStream.Read(bites, 0, Convert.ToInt32(memoryStream.Length));

	binaryWriter.Dispose();
	binaryWriter = null;

	memoryStream.Dispose();
	memoryStream = null;

	zipStream.Position = 0;
	zipStream.Write(bites, 0, bites.Length);

	zip.Close();

}	

public static Stream GetZipWriteStream(Package zip, string renamedFileName)
{

	//Replace spaces with an underscore (_) 
	string uriFileName = renamedFileName.Replace(" ", "_");

	//A Uri always starts with a forward slash "/" 
	string zipUri = string.Concat("/", Path.GetFileName(uriFileName));

	Uri partUri = new Uri(zipUri, UriKind.Relative);
	string contentType = "Zip"; // System.Net.Mime.MediaTypeNames.Application.Zip;

	//The PackagePart contains the information: 
	// Where to extract the file when it's extracted (partUri) 
	// The type of content stream (MIME type):  (contentType) 
	// The type of compression:  (CompressionOption.Normal)   
	PackagePart pkgPart = zip.CreatePart(partUri, contentType, CompressionOption.Normal);

	//Compress and write the bytes to the zip file 
	return pkgPart.GetStream();

}
Originally created by @xavierpena on GitHub (Jun 1, 2017). [This is the only example](https://stackoverflow.com/a/32305997/831138) that I've found that applies to writing to streams. I've tried to follow it and adapt it to my needs, but I am stuck at the exception it throws: using Microsoft.VisualStudio.TestTools.UnitTesting; using SharpCompress.Common; using SharpCompress.Compressors.Deflate; using SharpCompress.Writers; using System; using System.IO; namespace DbManager.DjdbCore.Tests { [TestClass] public class ZipTests { public ZipTests() { Directory.SetCurrentDirectory(AppContext.BaseDirectory); } [TestMethod] public void Test() { var zip = File.OpenWrite(@"..\..\..\..\..\test-resources\zip_file_test.zip"); var writerOptions = new WriterOptions(CompressionType.Deflate); var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions); var memoryStream = new MemoryStream(); var binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw"); var deflateStream = new DeflateStream(memoryStream, SharpCompress.Compressors.CompressionMode.Compress); deflateStream.Write(memoryStream.ToArray(), 0, Convert.ToInt32(memoryStream.Length)); // EXCEPTION: SharpCompress.Compressors.Deflate.ZlibException: 'Cannot Read after Writing.' // Source code: if (_streamMode != StreamMode.Reader) { throw new ZlibException("Cannot Read after Writing."); } zipWriter.Write("test_file_inside_zip.bin", deflateStream, DateTime.Now); zip.Flush(); zipWriter.Dispose(); zip.Dispose(); } } } In case it helps, this is what I used (and it worked, but only in dotnet core) using the library `System.IO.Compression`: private void WriteAsZipBinary() { //Open the zip file if it exists, else create a new one var zip = ZipPackage.Open(this.FileFullPath, FileMode.OpenOrCreate, FileAccess.ReadWrite); var zipStream = ZipManager.GetZipWriteStream(zip, nameOfFileInsideZip); var memoryStream = new MemoryStream(); var binaryWriter = new BinaryWriter(memoryStream); // Here is where strings etc are written to the binary file: WriteStuffInBinaryStream(ref binaryWriter); //Read all of the bytes from the file to add to the zip file byte[] bites = new byte[Convert.ToInt32(memoryStream.Length - 1) + 1]; memoryStream.Position = 0; memoryStream.Read(bites, 0, Convert.ToInt32(memoryStream.Length)); binaryWriter.Dispose(); binaryWriter = null; memoryStream.Dispose(); memoryStream = null; zipStream.Position = 0; zipStream.Write(bites, 0, bites.Length); zip.Close(); } public static Stream GetZipWriteStream(Package zip, string renamedFileName) { //Replace spaces with an underscore (_) string uriFileName = renamedFileName.Replace(" ", "_"); //A Uri always starts with a forward slash "/" string zipUri = string.Concat("/", Path.GetFileName(uriFileName)); Uri partUri = new Uri(zipUri, UriKind.Relative); string contentType = "Zip"; // System.Net.Mime.MediaTypeNames.Application.Zip; //The PackagePart contains the information: // Where to extract the file when it's extracted (partUri) // The type of content stream (MIME type): (contentType) // The type of compression: (CompressionOption.Normal) PackagePart pkgPart = zip.CreatePart(partUri, contentType, CompressionOption.Normal); //Compress and write the bytes to the zip file return pkgPart.GetStream(); }
claunia added the question label 2026-01-29 22:08:01 +00:00
Author
Owner

@adamhathcock commented on GitHub (Jun 1, 2017):

Your code should do something like this:

[TestMethod]
public void Test()
{            
    
    var writerOptions = new WriterOptions(CompressionType.Deflate);
    using(var zip = File.OpenWrite(@"..\..\..\..\..\test-resources\zip_file_test.zip"))
    using(var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions))
    {
        var memoryStream = new MemoryStream();            
        var binaryWriter = new BinaryWriter(memoryStream);
        binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw");

        memoryStream.Position = 0;
        zipWriter.Write("test_file_inside_zip.bin", memoryStream, DateTime.Now);						  
    }
}

2 things:

  1. You forgot to reset the MemoryStream after writing to it so it can be read.
  2. You don't need to manually use the DeflateStream. You've told the ZipWriter what compression to use. If it worked, you would have double compressed the bytes which would be garbage really.

Not sure the above code works as I didn't actually run it. Try it out.

@adamhathcock commented on GitHub (Jun 1, 2017): Your code should do something like this: ```csharp [TestMethod] public void Test() { var writerOptions = new WriterOptions(CompressionType.Deflate); using(var zip = File.OpenWrite(@"..\..\..\..\..\test-resources\zip_file_test.zip")) using(var zipWriter = WriterFactory.Open(zip, ArchiveType.Zip, writerOptions)) { var memoryStream = new MemoryStream(); var binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write("Test string inside binary file - text to fill it up: qoiwjqefñlawijfñlaskdjfioqwjefñalskvndñaskvnqo`wiefowainvñaslkfjnwpowiqjfeopwiqjnfjñlaskdjfñlasdfjiowiqjefñaslkdjfñalskjfpqwoiefjqw"); memoryStream.Position = 0; zipWriter.Write("test_file_inside_zip.bin", memoryStream, DateTime.Now); } } ``` 2 things: 1) You forgot to reset the MemoryStream after writing to it so it can be read. 2) You don't need to manually use the DeflateStream. You've told the ZipWriter what compression to use. If it worked, you would have double compressed the bytes which would be garbage really. Not sure the above code works as I didn't actually run it. Try it out.
Author
Owner

@xavierpena commented on GitHub (Jun 1, 2017):

Not sure the above code works as I didn't actually run it. Try it out.

It does! Thank you very much, that was it.

And thanks for providing an alternative to System.IO.Compression, that has given me nightmares because of the net46 compatibility issues.

@xavierpena commented on GitHub (Jun 1, 2017): > Not sure the above code works as I didn't actually run it. Try it out. It does! Thank you very much, that was it. And thanks for providing an alternative to `System.IO.Compression`, that [has given me nightmares](https://github.com/dotnet/corefx/issues/7702) because of the net46 compatibility issues.
Author
Owner

@adamhathcock commented on GitHub (Jun 1, 2017):

SharpCompress has long been backwards compatible :)

Though, I've been breaking things like silverlight/WP7 as they're no longer supported by Microsoft anyway.

@adamhathcock commented on GitHub (Jun 1, 2017): SharpCompress has long been backwards compatible :) Though, I've been breaking things like silverlight/WP7 as they're no longer supported by Microsoft anyway.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/sharpcompress#189