Tuesday, October 21, 2008

C# Tutorial - Filter Contents of a File Containing a Word or Phrase


Click the link to download the source code for this post

Licensing and Warranty

You may use the code as you wish - it may be used in commercial or other applications, and it may be redistributed and modified. The code is provided "as-is". No claim of suitability, guarantee, or any warranty whatsoever is provided. By downloading the code, you agree to defend, indemnify, and hold harmless the Author and the Publisher from and against any claims, suits, losses, damages, liabilities, costs, and expenses (including reasonable legal or attorneys' fees) resulting from or relating to any use of the code by you.




If any of you ever had to filter through Internet server logs to troubleshoot a problem (ex: every time someone accesses somepage.aspx, the server returns an HTTP error 500), you can understand how painful it can be - especially if your log has a lot of transactions in the file. I wrote this "quick-and-dirty" application to allow me to just filter out the lines that I'm looking for, and save the results to another file.
This application uses the System.IO library for file processing. It also uses the OpenFileDialog and SaveFileDialog objects to allow a person to select a file and save a file.

In a nutshell, this is what the application does:

  • It allows a user to type in a file name or select a file (using the OpenFileDialog object)

  • It allows the user to enter a word or phrase to look for (or leave the field blank for all the data)

  • It uses the System.IO object FileInfo to check the file size to see if it's greater than 5MB. (If it is, it warns the user that the file is large and asks if s/he wants to continue)

  • It uses the System.IO classes StreamReader and FileInfo to open and read the contents of the file

  • It uses the IndexOf function of the string class to find out whether the line contains the entered word or phrase (if one was entered)

  • For better memory management, it uses the StringBuilder to build the results

  • For saving the contents of the file, it uses the SaveFileDialog to allow the user to select where to save the contents. Then, it uses the System.IO classes Stream and StreamWriter to write the output to a file.



Here are some code snippets highlighting some of the things the application does:
Checking the file size and asking the user if s/he wants to continue
While I was using this, I found that large files really took awhile to load in the application. What I wanted to do to improve the user experience is to warn the user if s/he is trying to open a file that is greater than 5MB. I wanted to make sure that the user still wanted to continue. Here is the code snippet (found in Line 71 in the source):


// Check the size of the file
FileInfo fi = new FileInfo(txtFileName.Text);
// Warn user that the file is huge if file > 5 M
if (fi.Length > 5000000)
{
  DialogResult answer;
  answer = MessageBox.Show("The file you selected is large and may take some time to load. Are you sure you want to open this file", "Confirm Open Large File", MessageBoxButtons.YesNo);
  if (answer.ToString() == "No")
  {
    txtFileName.Focus();
    return;
  }
}


In this snippet, I am using the Length property of the FileInfo class to determine the size of the file. Since it returns the value in bytes, I need to check the byte size. Since I'm giving the user an "are you sure" type box, I need to be able to capture the results from the MessageBox. The DialogResult class is what the MessageBox returns when an action is taken (a button is clicked).
Notice that have a return statement. For you VB .NET programmers, this is the equivalent of an Exit Sub statement. Rather than put the code in a massive if-else loop, I just add the return statement to exit from the function if the user does not want to continue.

Setting the Filters for the OpenFileDialog and SaveFileDialog
By default, no filters are set. So when your user opens the dialog box, nothing will show up under the "File Type". In order to set the filters for text files only, do the following:


FileDialog.Filter = "Text Files|*.txt";


Where FileDialog is the instance of your OpenFileDialog or SaveFileDialog. The first part is the text to display in the drop-down box. The second part is the files to display that match the extension. Each section is separated by a pipe (|).
If you want to do multiple types, do the following:


FileDialog.Filter = "All Files|*.*|Text Files|*.txt";



Writing the contents of a text box to a file
I wanted to be able to write the filtered results to a file in case I need that file for other applications or purposes. Here is the code snippet (found on line 53 in the source):


// Get the contents of the text file
Stream saveStream = sfdContent.OpenFile();
StreamWriter sw = new StreamWriter(saveStream);
sw.Write(txtResults.Text);
sw.Close();


In this snippet, I am using the OpenFile function of the SaveFileDialog class (the instance is called sfdContent) to get the value entered by the user. I am then using the System.IO classes Stream and StreamWriter to take the contents of the text box and write it to a file.

I have placed a link to the source code for you to use to help with your studies. If you are looking for more practice, here are some suggestions for improving the application:

  • Make a progress bar so it will display when someone tries to open a large file

  • Give users the ability to change the "skin" of the application

  • Add a menu

  • Add an "About" option with release notes

  • Add a splash screen

  • Change the look and feel of the screen

No comments: