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;
}