Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

How to use GZipStream to extract a text log and list the result in a grid

2.00/5 (2 votes)
25 Feb 2010CDDL2 min read 1   312  
Using GZipStream to extract a text log and list the result in a grid.

Introduction

The purpose of this program is to use GZipStream to accomplish the following tasks:

  1. Extract all the text files from a .gz file using GzipStream
  2. Parse the text files and add them into the list
  3. Filter the list by day
  4. 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.

C#
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.

C#
static void Compress(FileInfo fi)
{
    // Get the stream of the source file.
    using (FileStream inFile = fi.OpenRead())
    {
        // Prevent compressing hidden and already compressed files.
        if ((File.GetAttributes(fi.FullName) & FileAttributes.Hidden)
                        != FileAttributes.Hidden & fi.Extension != ".gz")
        {
            // Create the compressed file.
            using (FileStream outFile = File.Create(fi.FullName + ".gz"))
            {
                using (GZipStream Compress = new GZipStream(outFile,
                               CompressionMode.Compress))
                {
                    // Copy the source file into the compression stream.
                    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.

C#
static void Decompress(FileInfo fi)
{
    // Get the stream of the source file.
    using (FileStream inFile = fi.OpenRead())
    {
        // Get original file extension, for example "doc" from report.doc.gz.
        string curFile = fi.FullName;
        string origName = curFile.Remove(curFile.Length - fi.Extension.Length);
    
        //Create the decompressed file.
        using (FileStream outFile = File.Create(origName))
        {
            using (GZipStream Decompress = new GZipStream(inFile,
            CompressionMode.Decompress))
            {
                //Copy the decompression stream into the output file.
                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.

C#
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;
            
            // Read and display lines from the file until the end of 
            // the file is reached.
            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.

C#
public static List<gzipmodel> Model(string path)
{
    List<gzipmodel> model = new List<gzipmodel>();

    // Path to directory of files to compress and decompress.
    string dirpath = path;

    DirectoryInfo di = new DirectoryInfo(dirpath);

    // Compress the directory's files.
    foreach (FileInfo fi in di.GetFiles())
    {
        Compress(fi);
    }

    // Decompress all *.gz files in the directory.
    foreach (FileInfo fi in di.GetFiles("*.gz"))
    {
        Decompress(fi);
    }

    List<gzipmodel> data = ParseFile(dirpath);
    GZipModel mode = new GZipModel();

    /// This will get all the data in thursday
    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.

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

gzipui.JPG

History

  • 26/02/2010 - Article added.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)