17

I have code that should do the compression:

FileStream fs = new FileStream("g:\\gj.txt", FileMode.Open);
FileStream fd = new FileStream("g:\\gj.zip", FileMode.Create);
GZipStream csStream = new GZipStream(fd, CompressionMode.Compress);

byte[] compressedBuffer = new byte[500];
int offset = 0;
int nRead;

nRead = fs.Read(compressedBuffer, offset, compressedBuffer.Length);
while (nRead > 0)
{
    csStream.Write(compressedBuffer, offset, nRead);
    offset = offset + nRead;
    nRead = fs.Read(compressedBuffer, offset, compressedBuffer.Length);
}

fd.Close();
fs.Close();

and I think it does, but I want to decompress what was compressed the way above. I do somethink like that:

FileStream fd = new FileStream("g:\\gj.new", FileMode.Create);
FileStream fs = new FileStream("g:\\gj.zip", FileMode.Open);
GZipStream csStream = new GZipStream(fs, CompressionMode.Decompress);

byte[] decompressedBuffer = new byte[500];
int offset = 0;
int nRead;

nRead=csStream.Read(decompressedBuffer, offset, decompressedBuffer.Length);
while (nRead > 0)
{
    fd.Write(decompressedBuffer, offset, nRead);
    offset = offset + nRead;
    nRead = csStream.Read(decompressedBuffer, offset, decompressedBuffer.Length);
}

fd.Close();
fs.Close();

and here it doesn't... I've got nRead = 0 befeore entering the loop... What I do wrong?? The test file I use is the simpliest TEXT file (size: 104 bytes)...

smn.tino
  • 2,272
  • 4
  • 32
  • 41

2 Answers2

24

My first thought is that you haven't closed csStream. If you use using this happens automatically. Since gzip buffers data, you could be missing some.

Secondly; don't increment offset; that is the offset in the buffer (not the stream). Leave at 0:

using (Stream fs = File.OpenRead("gj.txt"))
using (Stream fd = File.Create("gj.zip"))
using (Stream csStream = new GZipStream(fd, CompressionMode.Compress))
{
    byte[] buffer = new byte[1024];
    int nRead;
    while ((nRead = fs.Read(buffer, 0, buffer.Length))> 0)
    {
        csStream.Write(buffer, 0, nRead);
    }
}

using (Stream fd = File.Create("gj.new.txt"))
using (Stream fs = File.OpenRead("gj.zip"))
using (Stream csStream = new GZipStream(fs, CompressionMode.Decompress))
{
    byte[] buffer = new byte[1024];
    int nRead;
    while ((nRead = csStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        fd.Write(buffer, 0, nRead);
    }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • The problem is that commression works well, but cant make it to decompress. –  Oct 17 '09 at 08:12
  • 6
    Instead of the buffer loop you can also use the built in .CopyTo() function. In this case it would be: csStream.CopyTo(fd); – James Roland Jan 03 '11 at 23:56
  • 1
    @JamesR - not when this answer was written, I couldn't ;p – Marc Gravell Jan 04 '11 at 06:15
  • 3
    Good point, just adding to this bit of knowledge. One other annoying thing I found with GZipStream. If you are writing to a MemoryStream you have to .Close() the GZipStream. Otherwise it will hold on to the last few bytes. .Flush() does not seem to do the job. (This is if you use the MemoryStream inside the using statement.) – James Roland Jan 04 '11 at 17:55
  • @James indeed, but that is a side effect of GZIP itself; and at least you get the option (in the constructor) to have this **not** close the underlying stream. It affects all destinations, btw - not just MemoryStream. – Marc Gravell Jan 04 '11 at 17:58
10

The two methods I have are like James Roland mentioned.

private static byte[] Compress(HttpPostedFileBase file)
{
    using var to = new MemoryStream();
    using var gZipStream = new GZipStream(to, CompressionMode.Compress);
    file.InputStream.CopyTo(gZipStream);
    gZipStream.Flush();
    return to.ToArray();
}

private static byte[] Decompress(byte[] compressed)
{
    using var from = new MemoryStream(compressed);
    using var to = new MemoryStream();
    using var gZipStream = new GZipStream(from, CompressionMode.Decompress);
    gZipStream.CopyTo(to);
    return to.ToArray();
}

However, I'm using an upload with

Request.Files[0] 

then compress and save in the db. Then I pull the img out, decompress and set a src with

$"data:image/gif;base64,{ToBase64String(Decompress(img))}";
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
Stephen Himes
  • 655
  • 9
  • 13
  • Never use an `IDisposable` object without `using`! – JCKödel Mar 07 '18 at 23:56
  • 3
    @JCKödel Although it obviously preferred to take advantage of `using` when possible, saying "never" is just not accurate, and there are plenty of circumstances where it is not desired and/or possible. – ForeverZer0 Aug 22 '18 at 20:29
  • if you're not taking advantage of IDisposable and using syntax, then recommendation is to ensure using try/catch/finally and do not pass the stream from function to function (if you can avoid it). – Roman Mar 10 '20 at 19:10