zipping and unzipping streams

Aug 12, 2009 at 10:15 AM

Hi,

I probably miss something.

i want to send compressed data to WS, without using files. i want to create byte array of the zip file, send it to the WS, and at the WS extract the data into string and manipulate it there.

at the Compressing side i have the following code:

Stream st = new MemoryStream();
byte[] ba;
using (ZipFile zip = new ZipFile())
{
 zip.AddEntry("data.txt", "", bigSB.ToString());
 zip.Save(st);
 ba = new byte[st.Length];
 st.Write(ba, 0, ba.Length);
}
st.Close();
ws.send(ba);

 

Stream st = new MemoryStream();
using (ZipFile zip = ZipFile.Read(ba))
{
 zip[0].Extract(st);
}
StreamReader sr = new StreamReader(st);
string myData = sr.ReadToEnd();
sr.Close();

at the WS i got an exception:

ZipEntry::ReadHeader(): Bad signature (0x00000000) at position  0x00000000

 

what did i do wrong?

 

thnx

Coordinator
Aug 12, 2009 at 2:09 PM
Edited Aug 12, 2009 at 2:18 PM

Well you have a bunch of moving parts there.  You have the zip library, zipping into and out of streams.  You also have the web service communications across those two parts.You'll need good

I would have written the sending side like this:

 

byte[] ba;
using (var ms = new MemoryStream())
{
  using (ZipFile zip = new ZipFile())
  {
    zip.AddEntry("data.txt", "", bigSB.ToString());
    zip.Save(ms);
  }
  ba = ms.ToArray();
}
ws.send(ba);

 

On the other side I might have written it like this:

 

String x = null;
using (var ms = new MemoryStream())
{
    using (ZipFile zip = ZipFile.Read(ba))
    {
      zip[0].Extract(ms);
    }
    StreamReader sr = new StreamReader(ms, System.Text.Encoding.Default);
    x = sr.ReadToEnd();
}


But even if you get the ZIP part exactly right, you may still have problems.  You also have to ensure the communication across the wire is successful, and that on the receiving side, the byte array arrives intact.

It seems to me that all you want to do is compress a single string.  In this case using the ZipFile class is probably overkill.  A ZipFile is a multi-file compressed archive.  But you have just one thing to compress, and it is a string, not a file.   You might consider the use of the GZipStream class to compress and decompress just a single string. 

Looking at this just now, the code is more complicated that I thought it would be.  But this should work:

 

private byte[] CompressString(String s)
{
    var encoding = System.Text.Encoding.UTF8;
    byte[] uncompressed = encoding.GetBytes(s);

    using (var ms = new MemoryStream())
    {
        using (Stream compressor = new GZipStream(ms, CompressionMode.Compress, CompressionLevel.BestCompression))
        {
            compressor.Write(uncompressed, 0, uncompressed.Length);
        }
        return ms.ToArray();
    }
}

       
private String UncompressString(byte[] a)
{
    byte[] working = new byte[1024];
    var encoding = System.Text.Encoding.UTF8;
    using (var output = new MemoryStream())
    {
        using (var input = new MemoryStream(a))
        {
            using (Stream decompressor = new GZipStream(input, CompressionMode.Decompress))
            {
                int n;
                while ((n= decompressor.Read(working, 0, working.Length)) !=0)
                {
                    output.Write(working, 0, n);
                }
            }
            // reset to allow read from start
            output.Seek(0, SeekOrigin.Begin);
            var sr = new StreamReader(output, encoding);
            return sr.ReadToEnd();
        }
    }
}


 

 

Coordinator
Aug 12, 2009 at 2:21 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.