Introduction
The purpose of this program is to use GZipStream
to accomplish the following tasks:
- Extract all the text files from a .gz file using GzipStream
- Parse the text files and add them into the list
- Filter the list by day
- List the result in a grid using WPF
Background
What is GZipStream
used for? This is a class under System.IO.Compression
that provides methods and properties used to compress and decompress streams.
Data Instruction
We need to have a text log in a specific format. Here is an example data:
Bill, Campbelltown, IceMan1, 2010-02-18
Steve, Campbelltown, IceMan, 2010-02-18
Vioc, Townhall, Spiderman, 2010-02-18
Using the code
GZipStreamProject contains a C# class library, GZipCore, which has the following classes: GZipModel
and GzipBusiness
.
GZipModel
has all the property declarations that we later use to add the data from the text log.
public class GZipModel
{
public string Name { get; set; }
public string Address { get; set; }
public string Signature { get; set; }
public DateTime Date { get; set; }
}
GZipBusiness
: In this class, we have all the methods to compress and decompress, parse a file, and a model that will return a list object of type GZipModel
.
I used the System.IO
and Systen.IO.Compression
APIs to handle the file system. We first get the stream of the source file and add an 'if
' condition to prevent compressing hidden and already compressed files with an extension .gz.
static void Compress(FileInfo fi)
{
using (FileStream inFile = fi.OpenRead())
{
if ((File.GetAttributes(fi.FullName) & FileAttributes.Hidden)
!= FileAttributes.Hidden & fi.Extension != ".gz")
{
using (FileStream outFile = File.Create(fi.FullName + ".gz"))
{
using (GZipStream Compress = new GZipStream(outFile,
CompressionMode.Compress))
{
byte[] buffer = new byte[4096];
int numRead;
while ((numRead = inFile.Read(buffer, 0, buffer.Length)) != 0)
{
Compress.Write(buffer, 0, numRead);
}
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fi.Name, fi.Length.ToString(), outFile.Length.ToString());
}
}
}
}
}
In this method used to decompress a .gz file, we get the stream from the source file. It will get the extension from the original file and will decompress the file to the selected directory.
static void Decompress(FileInfo fi)
{
using (FileStream inFile = fi.OpenRead())
{
string curFile = fi.FullName;
string origName = curFile.Remove(curFile.Length - fi.Extension.Length);
using (FileStream outFile = File.Create(origName))
{
using (GZipStream Decompress = new GZipStream(inFile,
CompressionMode.Decompress))
{
byte[] buffer = new byte[4096];
int numRead;
while ((numRead = Decompress.Read(buffer, 0, buffer.Length)) != 0)
{
outFile.Write(buffer, 0, numRead);
}
Console.WriteLine("Decompressed: {0}", fi.Name);
}
}
}
}
We then parse the extracted file and add to the list collection. This method will also clean the data by assigning 'delimiter characters' to be removed from the extracted file using a 'split method' to convert the sting into an array that contains the substrings of every row of the text log data.
static List<gzipmodel> ParseFile(string path)
{
DirectoryInfo dir = new DirectoryInfo(path);
char[] delim = { ' ', '\t','\r','\n', '\\'};
List<gzipmodel> listinfo = new List<gzipmodel>();
foreach (FileInfo fi in dir.GetFiles("*.txt"))
{
using (StreamReader sr = new StreamReader(fi.FullName) )
{
String line;
while ((line = sr.ReadLine()) != null)
{
string[] data = line.Split(delim);
GZipModel model = new GZipModel();
if (data[0] != "")
{
model.Name = data[0].ToString();
model.Address = data[1].ToString();
model.Signature = data[2].ToString();
string dtString = data[3].ToString();
DateTime Date = DateTime.Parse(dtString);
model.Date = Date;
listinfo.Add(model);
}
}
}
}
return listinfo;
}
Following is the public method call to return the List
of type GZipModel
. I also filter the data to get all Thursday records in the text log, using a lambda expression.
public static List<gzipmodel> Model(string path)
{
List<gzipmodel> model = new List<gzipmodel>();
string dirpath = path;
DirectoryInfo di = new DirectoryInfo(dirpath);
foreach (FileInfo fi in di.GetFiles())
{
Compress(fi);
}
foreach (FileInfo fi in di.GetFiles("*.gz"))
{
Decompress(fi);
}
List<gzipmodel> data = ParseFile(dirpath);
GZipModel mode = new GZipModel();
var query = from n in data.Where(o => o.Date.DayOfWeek ==
DayOfWeek.Thursday )
select n;
return query.ToList();
}
Add a WPF Application project named GZipUI which will create two XAML files: ap.xaml and window1.xaml. Remove the Window1.xaml file and add a new window and name it Main.xaml. Now, we need to update the StartupURI
in App.xaml to point to Main.xaml.
You need to reference the WPFToolkit in your GZipUI. Download the WPF Toolkit from: http://wpf.codeplex.com/releases/view/29117.
I have two events in Main.xaml: btnBrowse_Click
to select the log data file path, and btnExtract_Click
will call GZipBusiness.Model
to get the data from the list.
Additionally, you need to reference System.Windows.Forms
to use the FolderBrowserDialog
API.
private void btnExtract_Click(object sender, RoutedEventArgs e)
{
var list = GZipCore.GZipBusiness.Mode(
this.textWebsiteRootPath.Text);
gridList.ItemsSource = list;
}
private void btnBrowse_Click(object sender, RoutedEventArgs e)
{
var browser = new System.Windows.Forms.FolderBrowserDialog
{
RootFolder = Environment.SpecialFolder.MyComputer,
SelectedPath = this.textWebsiteRootPath.Text,
};
var result = browser.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
this.textWebsiteRootPath.Text = browser.SelectedPath;
}
}
History
- 26/02/2010 - Article added.