Solved

SharpZipLib Inflate caused Unexpected Eof C#

Posted on 2010-08-19
6
3,008 Views
Last Modified: 2012-05-10
I am working in C# and using SharpZipLib as I am working with Silverlight and .NET.  I want to compress a file and decompress it prior to transfer to make sure that the file size is the same after decompression, just to catch any compression errors.  I have attached my code.  When I inflate the stream, the InflatorInputStream has zero length and I get an error "Unexpected Eof" when I try to read from the InflatorInputStream.  I have reset the position and all the online examples of decompressing a stream are all same.  Am I missing something?  
Just to add that I was using a small text file while testing.
private byte[] CompressFile(byte[] bytesIn)
        {
            MemoryStream ms = new MemoryStream();
            
            ICSharpCode.SharpZipLib.Zip.Compression.Deflater defl = new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(9, false);
            Stream s = new DeflaterOutputStream(ms, defl);
            s.Write(bytesIn, 0, bytesIn.Length);
            
            byte[] compressedData = (byte[])ms.ToArray();
            ms.Position = 0;
            MemoryStream ms2 = new MemoryStream(compressedData);
            ms2.Position = 0;
            ICSharpCode.SharpZipLib.Zip.Compression.Inflater inf = new ICSharpCode.SharpZipLib.Zip.Compression.Inflater(false);
            InflaterInputStream s2 = new InflaterInputStream(ms2, inf);
           
            byte[] decompressedBuffer = new byte[32768];
            int totalCount = ReadAllBytesFromStream(s2, decompressedBuffer);
            if (!CompareData(bytesIn, bytesIn.Length, decompressedBuffer, totalCount))
            {
                throw new Exception("Error when compressing the file");
            }
            s.Close();
            s2.Close();

            return compressedData;
        }


        public int ReadAllBytesFromStream(InflaterInputStream stream, byte[] buffer)
        {
            int offset = 0;
            int totalCount = 0;
            while (true)
            {
                int bytesRead = stream.Read(buffer, offset, buffer.Length);
                if (bytesRead <= 0)
                {
                    break;
                }
                offset += bytesRead;
                totalCount += bytesRead;
            }
            return totalCount;
        }

Open in new window

0
Comment
Question by:seashell1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 16

Expert Comment

by:Vikram Singh Saini
ID: 33482575
Hi,

Put your whole piece of code in try...catch block and let us know exactly which line is causing exception or error. and please let us know the whole exception details too.

Regards,
VSS
0
 
LVL 16

Expert Comment

by:Vikram Singh Saini
ID: 33482592
Hi,

Try this suggestion...I read it from google search. Put the line 10 code at line 4.

Regards,
VSS
0
 

Author Comment

by:seashell1
ID: 33483505
Sorry, I didn't really explain properly, but the error happens at line 35.
Compressing works from lines 3-9 and the compressedData does contain 2 bytes of information with a length of 233. I think ms2 successfully contains the compressedData and it's only when I put it into the InflaterInputStream s2 that it's empty.
I have tried you're suggestion to move line 10 to line 4, but this still did not work
0
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
LVL 16

Expert Comment

by:Vikram Singh Saini
ID: 33485072
Hi,

The problem actually lies at line number 14 which is reflected later on line number 35. Actually as I have learn till far by searching on google and trying the same code myself the InflaterInputStream constructor is not able to put values in its object. Line 14 says that the object is having length of zero means it is not having any values in it.

By the way I am trying for it.  If you get solution in between please let me know too. Searching online goes worst with no worthy solution.

Regards,
VSS
0
 
LVL 16

Expert Comment

by:Vikram Singh Saini
ID: 33499898
Hi,

I am still working on your code. And here is the report of something which I tried to find out more about it:

// Returns 0 once the end of the stream (EOF) has been reached. Otherwise returns 1.
            int EOF = s2.Available;
            bool timeout = s2.CanTimeout;
            lblMessage.Text = "EOF: " + EOF.ToString() + "||" + "TimeOut: " + timeout.ToString();

// The output I got is as EOF: 1|| TimeOut: False

So I concluded that it seems that the InflaterInputStream s2 is not stopping itself from reading the MemoryStream we are supply.

Regards,
V.S.Saini
0
 

Accepted Solution

by:
seashell1 earned 0 total points
ID: 33539953
I couldn't get this working so I've abandoned this method and found someone else's compression and decompression code instead, which works.  I've attached the code that I am using now for anyone else who wants to use it.  
public MemoryStream CreateToZipMemoryStream(MemoryStream memStreamIn, string filename)
        {
            MemoryStream memStreamOut = new MemoryStream();
            using (ZipOutputStream s = new
                     ZipOutputStream(memStreamOut))
            {
                s.SetLevel(9); // 0-9, 9 being the highest compression

                byte[] buffer = new byte[4096];
                ZipEntry entry = new ZipEntry(filename);
                entry.DateTime = DateTime.Now;
                s.PutNextEntry(entry);
                int sourceBytes;
                do
                {
                    sourceBytes = memStreamIn.Read(buffer, 0,buffer.Length);
                    s.Write(buffer, 0, sourceBytes);
                } while (sourceBytes > 0);

                s.Finish();
                s.Close();
            }
            return memStreamOut;
        }

        public MemoryStream CreateFromZipMemoryStream(byte[] compressedData, string filename, int origFileLength)
        {
            MemoryStream output = new MemoryStream();
            ZipFile zf = null;
            try
            {
                MemoryStream ms = new MemoryStream(compressedData);
                zf = new ZipFile(ms);
                ZipEntry zipEntry = zf.GetEntry(filename);
                String entryFileName = zipEntry.Name;
                               
                Stream zipStream = zf.GetInputStream(zipEntry);
                byte[] buffer = ReadFully(zipStream, origFileLength);                
                output = new MemoryStream(buffer);                     
            }
            finally
            {
                if (zf != null)
                {
                    zf.IsStreamOwner = true; // Makes close also shut the underlying stream
                    zf.Close(); // Ensure we release resources
                }
            }

            return output;
        }


        private byte[] CompressFile(byte[] bytesIn)
        {
            MemoryStream ms = new MemoryStream(bytesIn);
            MemoryStream outputZip = CreateToZipMemoryStream(ms, "temp");
            
            // Use the newly created memory stream for the compressed data.            
            byte[] compressedData = (byte[])outputZip.ToArray();


            MemoryStream ms2 = CreateFromZipMemoryStream(compressedData, "temp", bytesIn.Length);
            byte[] decompressedBuffer = (byte[])ms2.ToArray();
            if (!CompareData(bytesIn, bytesIn.Length, decompressedBuffer, decompressedBuffer.Length))
            {
                throw new Exception("Error when compressing the file");
            }                        

            return compressedData;
        }


        public byte[] ReadFully(Stream stream, int initialLength)
        {
            // If we've been passed an unhelpful initial length, just
            // use 32K.
            if (initialLength < 1)
            {
                initialLength = 32768;
            }

            byte[] buffer = new byte[initialLength];
            int read = 0;

            int chunk;
            while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
            {
                read += chunk;

                // If we've reached the end of our buffer, check to see if there's
                // any more information
                if (read == buffer.Length)
                {
                    int nextByte = stream.ReadByte();

                    // End of stream? If so, we're done
                    if (nextByte == -1)
                    {
                        return buffer;
                    }

                    // Nope. Resize the buffer, put in the byte we've just
                    // read, and continue
                    byte[] newBuffer = new byte[buffer.Length * 2];
                    Array.Copy(buffer, newBuffer, buffer.Length);
                    newBuffer[read] = (byte)nextByte;
                    buffer = newBuffer;
                    read++;
                }
            }
            // Buffer is now too big. Shrink it.
            byte[] ret = new byte[read];
            Array.Copy(buffer, ret, read);
            return ret;
        }

Open in new window

0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Suggested Courses

631 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question