C# zipped streams not being recognized

Hey everyone! Sometimes no matter how good you think you are, there is always something that stumps you which turns out to be quite silly and simple. I had one of those situations the other day while using the DotNetZip libraries to zip and unzip streams and byte arrays for storing and retrieving zip files that are stored as a BLOB in a database. I have to say the library is great and if you haven’t messed with it before or are in need of a library that handles all the BS to zip and unzip a file, you should Go Here on CodePlex and check it out. .NET does in fact have the capabilities to do what they do in this library, but it is very convoluted and needs a lot of patience to get it going. DonNetZip acts as a wrapper around these .NET functionalities to make it easier to accomplish any zip and unzip tasks.

So enough about that. What I really wanted to talk about was streams and some things I didn’t realize about them (but makes sense). So I had a few methods that would create  zip files as Streams, from streams etc… and at the end would always convert it all to a byte array to be pushed to the BLOB column in the database.when I was saving things to file, everything worked great, but when I used a FileStream from a local zipped file and tried to Read the zip file using the libraries, it came back with the following exception error “Cannot read Block, No data“. For those of you interested in the code, I placed a question on www.stackoverflow.com located here.  The answer ended up being to add the following line of code

stream.Seek(0, SeekOrigin.Begin);

Now, my question was not to the above code, it was to find out why, because I really wasn’t sure why it was necessary. I got lucky and stumbled on it in troubleshooting, but I’m the kind of developer that like to understand why something works. It turns out that when you write to a stream, the position of the stream is wherever it last wrote to, in most cases the end of the stream. This will cause an issue when you read the stream because .NET does not recognize this and start at the beginning. It assumes that you know what you are doing and just blindly reads from it’s current position and fails to find a zip file because the stream is at it’s end, so the headers that determine that it’s a zip file are no longer to be found. Furthermore, it thinks there is no data at all because you are at the end of the stream.

A great analogy that was written in the answer to my stack question was that it is similar to the old cassette tapes or VHS tapes for those of you that remember this. When you record something (write to it), when you are at the end, what do you need to do to rewatch it? REWIND! Ahh… the epiphany has come to light. It all makes sense now right?

So the above code is meant to seek a particular position in the stream. Since we are telling it to start from the beginning and find position 0, it goes to the beginning (REWINDS) and stays there at position 0. Another way to accomplish the same task is to set the Position property on the Stream after the stream is written to so that when you go to read it, it starts at 0. The following is an example of this.

public Stream ZipObject(Stream data)
{
    var output = new MemoryStream();
    using (var zip = new ZipFile())
    {
        zip.AddEntry(Name, data);
        zip.Save(output);
    }
    output.Position = 0;
    return output;
}

Both do the same thing and both are just as efficient, setting the position property is probably the cleaner and more readable of the two for future development, which is what I am always thinking about because my memory is horrid and I need simple things to remind my brain what I was thinking at the time I wrote the code Smile

 

Until Next Time.. Happy Coding!Smile

Advertisements

About Gregg Coleman

I am Senior-level Software Engineer working primarily these days with .NET. I have a good working knowledge of ASP.NET MVC, Web Forms, WCF web services and Windows Services. I spend much of my time in the Web Services (SOAP and REST) world in my current job designing and implementing various SOA architectures. I have been in the software engineering industry for about 6 years now and will not now nor ever consider myself an "expert" in programming because there is always so much to learn. My favorite thing about designing software is there are always new emerging technologies and something to learn every day! My current job has me spending much of my job on the bleeding edge of technologies and changing gears all the time, so I'm never bored and always challenged. On my spare time I enjoy weight training, reading and venturing to new places near by. Of course programing and learning new technologies are another hobby of mine.
This entry was posted in .NET, .NET 4.5, C#, Classes, Programming and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s