Invalid bytes from memory stream

May 19, 2010 at 2:12 PM

Hi

I am trying to obtain a byte array from a newly generated zip file and generate the zipfile from these bytes at a remote server. For this I tried to use a Memory stream and construct the zip file from the bytes obtained from this stream. However, if I open the zipfile, Windows will report that the file is corrupt.

My temporary solution is to first write the zip file to the file system and read the file using a file stream. From the file stream I can then obtain the bytes for transportation and reconstruction at the remote server. But for us it is not desirable to write to the file system.

So my question is why can't I use the bytes obtained from the memory stream? Is there a solution to this problem?

Coordinator
May 19, 2010 at 2:16 PM

Without seeing your code, I Can't say for sure what the problem is.

By far the most common problem when saving a zipfile to a memorystream , is that developers try to read the memorystream before resetting the cursor in it, back to the beginning. In other words, they write to the stream, then immediate try to read.  Of course, that means the cursor is at the end-of-stream, and no bytes can be read at all.  The solution is to call Seek() on the stream to reset the cursor to the beginning.   This problem gets reported, oh, I'd say, every week or two, here on the forums .

Without seeing your code there's no way for me to know if this is the problem you're seeing.

 

May 19, 2010 at 3:40 PM

 

Thanks for the reply!
Below is the code I am using:
 using (MemoryStream ms = new MemoryStream())
                {
                    using (ZipOutputStream zos = new ZipOutputStream(ms))
                    {
                        zos.PutNextEntry(string.Format("TMC{0}.jpg", orderID));
                        zos.Write(cardImage, 0, cardImage.Length);
                        
                        zos.Close();
                    }

                    bytes = ms.GetBuffer();
                }

                using (FileStream output = File.Create(path + @"\potest.zip"))
                {
                    output.Write(bytes, 0, bytes.Length);
                }

                using (ZipFile zipFile = ZipFile.Read(path + @"\potest.zip"))
                {
                    int count = zipFile.Count;
                    input.Text = count.ToString();
                }

Indeed I didn't reset the stream, but even if I do as below I still get the same error.
using (MemoryStream ms = new MemoryStream())
                {
                   using (ZipFile zipfile = new ZipFile())
                    {
                        zipfile.AddEntry(string.Format("TMC{0}.jpg", orderID), cardImage);
                        zipfile.Save(ms);
                    }
                    ms.Seek(0, SeekOrigin.Begin);
                    bytes = ms.GetBuffer();
                }

                using (FileStream output = File.Create(path + @"\potest.zip"))
                {
                    output.Write(bytes, 0, bytes.Length);
                }


 

May 19, 2010 at 4:03 PM

One issue might be to do with using GetBuffer. See the "Remarks" section in http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer.aspx.

"Note that the buffer contains allocated bytes which might be unused. For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused."

You could try changing this:

using (FileStream output = File.Create(path + @"\potest.zip"))
{
    output.Write(bytes, 0, bytes.Length);
}

to this


using (FileStream output = File.Create(path + @"\potest.zip"))
{
    output.Write(bytes, 0, ms.Length);
}

but I haven't tested that myself so it's just a guess. There might also be something else going on - if you can post the original and compressed file it would help.

M

Coordinator
May 19, 2010 at 4:03 PM

I think you're doing it wrong.

MemoryStream.GetBuffer returns the array of bytes from which the memorystream was created. I don't know what you would get if you create the memory stream with no argument.

What you want is the ToArray() to get the byte array.

using (MemoryStream ms = new MemoryStream())
{
    using (ZipFile zipfile = new ZipFile())
    {
        zipfile.AddEntry(string.Format("TMC{0}.jpg", orderID), cardImage);
        zipfile.Save(ms);
    }
    bytes = ms.ToArray();
}

using (FileStream output = File.Create(path + @"\potest.zip"))
{
    output.Write(bytes, 0, bytes.Length);
}
May 19, 2010 at 4:10 PM

Thanks Cheeso!!!! That solved my problem indeed.