Sharing the information you need to get development done!
Welcome to DevAuthority.Com Sign in | Join | Help
in Search

be-#

DeflateStream/GZipStream: Be sure to compress an entire buffer -- not one byte at a time!

I was playing around with .net 2.0's DeflateStream, which compresses streams using the GZip algorithm.  There's two different kinds of compression streams in .net 2.0.  There's DeflateStream, which compresses files without the GZip header, which means it compresses files but can't be read by GZip.  There's also GZipStream, which includes the header, and can be read by GZip.

But that's not what I'm here to talk about.

While playing with it I discovered that all of my compressed files were actually bigger than their non-compressed source files.  The trick turned out to be that you shouldn't try to compress one byte at a time -- you should compress an entire byte buffer at once.  Examples follow.  I also include a decompress function because you can't have ying without yang.  I use file paths as parameters to these functions, but in an enterprise environment that stresses reuse, generally it would be better to use streams as parameters, as that's a far more generic input.

FYI, the original file is a simple text file.  Sizes:

  • 2772 - Original size
  • 3062 - Byte-by-Byte compression - bad!
  •   143 - Buffer compression - that's more like it!

//BAD!

void CompressTheFileByte(string uncompressedFileFullPath, string compressedFileFullPath)
{
    FileStream fsCompressed = new FileStream(compressedFileFullPath, FileMode.OpenOrCreate);

    using (FileStream fsSource = new FileStream(uncompressedFileFullPath, FileMode.Open))
    using (DeflateStream deflate = new DeflateStream(fsCompressed, CompressionMode.Compress))
    {
        for (int by = fsSource.ReadByte(); by != -1; by = fsSource.ReadByte())
            deflate.WriteByte((Byte)by);
    }
}

//GOOD!

void CompressTheFileBuffer(string uncompressedFileFullPath, string compressedFileFullPath)
{
    FileStream fsCompressed = new FileStream(compressedFileFullPath, FileMode.OpenOrCreate);

     using (DeflateStream deflate = new DeflateStream(fsCompressed, CompressionMode.Compress))
    {
        Byte[] theBytes = File.ReadAllBytes(uncompressedFileFullPath);
        deflate.Write(theBytes, 0, theBytes.Length);
    }
}

//Decompress:

void DecompressTheFile(string compressedFileFullPath, Stream destStream)
{
    FileStream fsCompressed = File.OpenRead(compressedFileFullPath);

    Console.WriteLine(fsCompressed.Length);

    using (DeflateStream deflate = new DeflateStream(fsCompressed, CompressionMode.Decompress))
    {
        for (int myByte = deflate.ReadByte(); myByte != -1; myByte = deflate.ReadByte())
             destStream.WriteByte((byte)myByte);
    }

    destStream.Position = 0;
}

Published Thursday, October 18, 2007 11:36 AM by ebuatois

Comments

 

artas said:

Compression ratios can be improved even further, but you will need to use another component that is a drop-in replacement for the System.IO.Compression classes. Check out www.dotnetgzip.com and take a look at the size comparisons there.
October 19, 2007 1:12 AM
Anonymous comments are disabled







This Blog

Post Calendar

<October 2007>
SuMoTuWeThFrSa
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Syndication



Powered by Community Server, by Telligent Systems