Introduction
The.NET framework provides us a way to compress and decompress data using the classes under the System.IO.Compression. There are two main classes that perform the job, namely the GZipStream class and the DeflateStream class. Both use the same algorithm to compress and decompress data but there are some differences. In fact, GZipStream method supports more formats specifications that DeflateStream method something that renders the compressed files according to the GZipStream more used in a multiplatform context that uses GZip method to compress and decompress files. In the other hand, the Deflate stream method is recommended if we are using compressed and decompressed files in a single platform context for example the same machine is used to compress, decompress and use the handled files at the same time because DeflateStream method, unlike the GZipStream, doesn't support additional information, flags and headers that facilitate the operation across different platforms. Hence, it will be considered are optimal solution for a mono platform.
In this article, I propose this solution that helps to compress and decompress files. First this is a class that uses GZipStream class.
using System;
using System.IO;
using System.IO.Compression;
namespace appWin
{
/// <summary>
/// This enumeration enables the user to specify the mode (zip or unzip).
/// </summary>
public enum Action { Zip, UnZip }
/// <summary>
/// This class performs file compression and decompression.
/// </summary>
public class GZip
{
private string _SourceFileName = ""; // Full source file path
private string _DestinationFileName = ""; // Full destination file path
private byte[] oBuffer; // Byte array to store file contents
private GZipStream oZipper; // Handles zipping and unzipping
/// <summary>
/// Default constructor.
/// </summary>
public GZip() { }
/// <summary>
/// Overloaded constructor to specify source and destination files and the action (zip or unzip).
/// </summary>
public GZip(string sourceFileName, string destinationFileName, Action action)
{
oZipper = null;
SourceFileName = sourceFileName;
DestinationFileName = destinationFileName;
// Perform the appropriate action based on the specified mode
if (action == Action.Zip)
CompressFile();
else if (action == Action.UnZip)
DecompressFile();
}
/// <summary>
/// Source file full path property.
/// </summary>
public string SourceFileName
{
get { return _SourceFileName; }
set { _SourceFileName = value; }
}
/// <summary>
/// Destination full path property.
/// </summary>
public string DestinationFileName
{
get { return _DestinationFileName; }
set { _DestinationFileName = value; }
}
/// <summary>
/// Method responsible for compression (marked as protected because it's used at the constructor level).
/// </summary>
protected void CompressFile()
{
if (File.Exists(SourceFileName))
{
using (FileStream inputFile = File.Open(SourceFileName, FileMode.Open),
outputFile = File.Create(DestinationFileName))
{
using (oZipper = new GZipStream(outputFile, CompressionMode.Compress))
{
oBuffer = new byte[inputFile.Length];
int counter = 0;
while ((counter = inputFile.Read(oBuffer, 0, oBuffer.Length)) != 0)
{
oZipper.Write(oBuffer, 0, counter);
}
}
oBuffer = null;
}
}
// TO DO: Notify user that the task is performed
}
/// <summary>
/// Method responsible for decompression (marked as protected because it's used at the constructor level).
/// </summary>
protected void DecompressFile()
{
if (File.Exists(SourceFileName))
{
using (FileStream inputFile = File.Open(SourceFileName, FileMode.Open),
outputFile = File.Create(DestinationFileName))
{
using (oZipper = new GZipStream(inputFile, CompressionMode.Decompress))
{
oBuffer = new byte[inputFile.Length];
int counter;
while ((counter = oZipper.Read(oBuffer, 0, oBuffer.Length)) != 0)
{
outputFile.Write(oBuffer, 0, counter);
}
}
oBuffer = null;
}
}
// TO DO: Notify user that the task is performed
// MessageBox.Show("Decompression done");
}
}
}
Now, in order to consume the class service here you is the code.
private void button1_Click(object sender, EventArgs e)
{
GZip oZip = new GZip(@"C:\Test.txt", @"C:\Test1.txt", Action.Zip);
oZip = new GZip(@"C:\Test1.txt", @"C:\Test2.txt", Action.UnZip);
}
This is another class but that uses DeflateStream class.
using System;
using System.IO;
using System.IO.Compression;
namespace appWin
{
/// <summary>
/// This enumeration enables the user to specify the mode (zip or unzip).
/// </summary>
public enum Action { Zip, UnZip }
/// <summary>
/// This class performs file compression and decompression.
/// </summary>
public class Deflat
{
private string _SourceFileName = "";
private string _DestinationFileName = "";
private byte[] oBuffer;
private DeflateStream oZipper;
/// <summary>
/// Default constructor.
/// </summary>
public Deflat() { }
/// <summary>
/// Overloaded constructor to specify source and destination files and the action (zip or unzip).
/// </summary>
public Deflat(string sourceFileName, string destinationFileName, Action action)
{
oZipper = null;
SourceFileName = sourceFileName;
DestinationFileName = destinationFileName;
if (action == Action.Zip)
CompressFile();
else if (action == Action.UnZip)
DecompressFile();
}
public string SourceFileName
{
get { return _SourceFileName; }
set { _SourceFileName = value; }
}
public string DestinationFileName
{
get { return _DestinationFileName; }
set { _DestinationFileName = value; }
}
protected void CompressFile()
{
if (File.Exists(SourceFileName))
{
using (FileStream inputFile = File.Open(SourceFileName, FileMode.Open),
outputFile = File.Create(DestinationFileName))
{
using (oZipper = new DeflateStream(outputFile, CompressionMode.Compress))
{
oBuffer = new byte[inputFile.Length];
int counter = 0;
while ((counter = inputFile.Read(oBuffer, 0, oBuffer.Length)) != 0)
{
oZipper.Write(oBuffer, 0, counter);
}
}
oBuffer = null;
}
}
Console.WriteLine("Compression done");
}
protected void DecompressFile()
{
if (File.Exists(SourceFileName))
{
using (FileStream inputFile = File.Open(SourceFileName, FileMode.Open),
outputFile = File.Create(DestinationFileName))
{
using (oZipper = new DeflateStream(inputFile, CompressionMode.Decompress))
{
oBuffer = new byte[inputFile.Length];
int counter;
while ((counter = oZipper.Read(oBuffer, 0, oBuffer.Length)) != 0)
{
outputFile.Write(oBuffer, 0, counter);
}
}
oBuffer = null;
}
}
// TO DO: Notify the user that the action is performed
}
}
}
Now, in order to consume the class service here you is the code
private void button1_Click(object sender, EventArgs e)
{
GZip oZip = new GZip(@"C:\Test.txt", @"C:\Test1.txt", Action.Zip);
oZip = new GZip(@"C:\Test1.txt", @"C:\Test2.txt", Action.UnZip);
}
I have marked the methods compress and decompress as protected in order do not to be used directly, instead in provide the choice for the developer via the enumeration Action to choose witch mode will be used and then the both methods are triggered from the constructor. This is more simple and elegant from my point of view.
Finally, and in order to provide more flexibility and more possibilities for developers to extend the both classes you can extract an interface as below:
using System;
namespace appWin
{
interface IZipUnZip
{
/// <summary>
/// This is the full path of the source path
/// </summary>
string DestinationFileName { get; set; }
/// <summary>
/// This is the full path of the destination path
/// </summary>
string SourceFileName { get; set; }
}
}
Then make the both classes implement this interface
/// <summary>
/// This class performs files compression and decompression
/// </summary>
public class Deflat : appWin.IZipUnZip
{
.
.
.
]
/// <summary>
/// This class performs files compression and decompression
/// </summary>
public class Deflat : appWin.IZipUnZip
{
That's it
Good Dotneting!!!