don’t know about you, but I fight a constant battle with weight. I’m sedentary, writing and coding, 99 percent of the time. The occasional huffing and puffing on the bicycle up and down the local hills doesn’t really count. (I suppose it doesn’t hurt, either?until I keel over from a heart attack. We’ve got serious hills here.) In 2000, I lost 60 pounds, pushed over the edge by that last Baskin-Robbins Banana Royale. Since then, the weight has been creeping back up, in a rather scary fashion. I’m working on it, again. Like most people in my situation, I’ve gained and lost several times my body weight over my 50 years. I’d take suggestions on how to keep it off, but it’s actually quite simple. Eat less. Exercise more. I know.
The .NET Framework has correspondingly allowed you to put streaming content “on a diet.” Although it was possible in previous versions of the framework to use add-on tools to compress data, the 2.0 version of the framework includes the System.IO.Compression namespace, which makes it easy to compress data. To avoid patent issues, this namespace doesn’t support the commonly used ZIP compression format. Instead, it uses the GZIP (Gnu ZIP) format, which has no patent restrictions. (I can’t be the only one who finds the irony in this?Microsoft embracing an open source solution, so as to avoid copyright issues? I love it.) What this means, of course, is that if you buy into this technology, you’re compressing files for use only by your application (or for other .NET applications that use the same compression algorithm, or for the few Windows users who have bought into the GZIP format). This isn’t actually a problem if your point is to store your data in a compressed format so that your application can load it again later.
Rather than focus on a story this time, I’ll jump right into the code?there’s a lot of it. If you want to compress and decompress files, you’ll need to reference the appropriate namespaces:
' [VB] Imports System.IO Imports System.IO.Compression // [C#] using System.IO; using System.IO.Compression;
Once you’ve imported the System.IO.Compression namespace, compressing a file really isn’t much more difficult than simply copying a file. You must iterate through the contents of the file, reading a buffer full of data (I’ve used a 10000-byte buffer, but you may want to alter that size to fit your own needs), and then writing the buffer to a GZipStream instance that “wraps” a FileStream instance. The GZipStream class uses the standard GZIP algorithm for its compression, but you can supposedly override the compression algorithm. The documentation is unsurprisingly mute on this particular topic. Listing 1 shows a simple procedure you can use for compressing a file. The only interesting feature of this procedure is the use of the GZipStream, which takes in its constructor a stream to which it writes its compressed output. The sample procedure reads a buffer of data, and then writes the buffer to the compressed stream, performing compression as it writes. (The documentation for the GZipStream class indicates that you cannot use this algorithm for files larger than 4GB. I haven’t tested that restriction. Feel free to try it when you have some time to kill.) In addition, the GZipStream class provides a large number of members I haven’t even mentioned here?see the .NET Framework documentation for more information.
Listing 2 lists the corresponding decompression procedure. This procedure works much like the compression procedure, except that this time, the code reads from the compressed stream, which wraps the input file stream.
To call the compression and decompression procedures, you can write code like this:
[VB] CompressFile(PATH, GZIPPATH) DecompressFile(GZIPPATH, UNGZIPPATH) [C#] CompressFile(PATH, GZIPPATH); DecompressFile(GZIPPATH, UNGZIPPATH);
In these examples, the constants represent paths for the original, compressed, and uncompressed files. (I did compare the original and the uncompressed files. Luckily, they compared exactly. The GZIP format specifies a lossless compression. Good thing!)
Because the GZipStream class wraps another stream instance, you can also use the class to compress data as it’s serialized. That is, when you call the Serialize or Deserialize method of a formatter (BinaryFormatter or SoapFormatter), you can pass an initialized GZipStream instance and your data will automatically be compressed and decompressed as part of the serialization/deserialization process.
I may not be successful at losing weight, but your files can be, taking advantage of the GZipStream class in the .NET Framework 2.0. As a fun experiment, try compressing a file using GZipStream, and then using the standard ZIP format. You’ll find that GZipStream isn’t quite as efficient, fast, or compact as the ZIP format. But it doesn’t have patent restrictions. And I guess that’s all that really matters.