File, Directory, Stream and Registry Classes in .Net

 

The System.IO namespace contains many file and directory related classes. Five of these important classes that let us manipulate and explore files and directories are:

 

Examples: (Files are always tied to stream objects for reading or writing to them)

Stream fs = File.Open(@"c:\temp\t1.txt",FileAccess.Read);

 

    File.Copy(@"c:\temp\source.txt",@"c:\temp\dest.txt");

 

Example:

                  FileInfo fr = new FileInfo(@"c:\temp\t1.txt"); // input file

                  StreamReader reader = fr.OpenText();  // OpenText returns StreamReader

 

         // Test to see if file exists

         string file = “c:\\temp\\t1.txt”;

         FileInfo fileUnderTest = new FileInfo(file);

         if (fileUnderTest.Exists)

         {

           // do something with the file

           return;

         }

         // otherwise not a file or directory

         throw new FileNotFoundException("No file called:"+file);

 

Example:

                Directory.CreateDirectory(@"c:\\temp");

 

Example:

      dirName = "c:\\temp";

      DirectoryInfo dir = new DirectoryInfo(dirName);

      if (!dir.Exists)

        throw new DirectoryNotFoundException

          ("directory does not exist:"+dirName);

      // fill the directory listbox

      foreach(DirectoryInfo di in dir.GetDirectories())

        lstFolders.Items.Add(di.Name);

     

      // fill the Files listbox

      foreach(FileInfo fi in dir.GetFiles())

     lstFiles.Items.Add(fi.Name);

 

string fpath = Path.Combine(@”c:\temp”, “t1.txt”);

 

We will create a windows application to view a given directory’s contents and to list the different attributes of a file in it.

 

Example: Create a new windows type project. Name the project FileDirInfo. Place some labels, buttons and text boxes on the form as shown below.

 

 

The names of the top text box where the directory name will be typed is: txtDirectory. The button next to it has a name of btnExamine, and the “Move Up” button has a name of btnMoveUp. The filter text box has a name of txtFilter and the button next to it has a name of btnFilter.

 

The two list boxes in the middle of the form have names of lstFiles and lstFolders. The four labels with dark boundaries (BorderStyle property of FixedSingle) are contained inside a group box. These labels have names of lblFileName, lblFileSize, lblCreationTime, and lblLastAccessed respectively. Finally the exit button has a name of btnExit.

 

Add the following using statement close to the top of the form code.

using System.IO;

 

Add the following data member (shown in bold) to the form class:

     public class Form1 : System.Windows.Forms.Form

     {

          private string currentDirectory;

 

Exercise: Write a control clearing function called “ClearAllControls( )” that will clear out every control except the fixed type of labels, and except the top text box that contains the directory to be examined.

Hint: Use the Controls collection in the form. Remember the controls in the group box need to handled as a separate Controls collection in the group box. If you are unsuccessful at writing the code, the solution is given at the end of this handout.

 

    private void ClearAllControls()

    { 

      // instead explicitly clearing a control by

      // its name, it is better to do it through

      // forms collection. This way, if you added

      // a control in the future, it will get cleared.

 

      // do not clear top edit box that contains directory name

    }

 

Write a general purpose function called “DisplayFiles(string dirName )” that takes the directory name as a parameter and populates the two list boxes (lstFiles and lstFolders with the files and folders contained within the parameter dirName directory i.e., the lstFiles list box is populated with the files in the dirName directory and the lstFolders list box is populated with the folders in the dirName directory.

The code for this function will look as:

 

    private void DisplayFiles(string dirName)

    {

      // test to see if directory exists

      DirectoryInfo dir = new DirectoryInfo(dirName);

      if (!dir.Exists)

        throw new DirectoryNotFoundException

          ("directory does not exist:"+dirName);

      // fill the directory listbox

      foreach(DirectoryInfo di in dir.GetDirectories())

        lstFolders.Items.Add(di.Name);

     

      // fill the Files listbox

      foreach(FileInfo fi in dir.GetFiles())

        lstFiles.Items.Add(fi.Name);

    }

 

Now that we have our two support functions (ClearAllControls( ) and DisplayFiles( ), we can write the code for the different event handlers.

 

Write the following event handler for the “Examine Directory” button (btnExamine) event handler.

 

private void btnExamine_Click(object sender, System.EventArgs e)

    {

      try

      {

        string dir = txtDirectory.Text;

        ClearAllControls();

        DirectoryInfo dinfo = new DirectoryInfo(dir);

        if (dinfo.Exists)

        {

          currentDirectory = dir;

          DisplayFiles(dinfo.FullName); // populate left list box

          return; // valid directory

        }

       

        // otherwise check to see if it is a file

        FileInfo fileTest = new FileInfo(dir);

        if (fileTest.Exists)

        {

          DisplayFiles(fileTest.Directory.FullName);

          int index = lstFiles.Items.IndexOf(fileTest.Name);

          lstFiles.SetSelected(index,true);

          return;

        }

 

        // otherwise not a file or directory

        throw new FileNotFoundException(

          "No file or directory called:"+dir);

      }

      catch (Exception ex)

      {

        MessageBox.Show(ex.Message);

      }

    }

When someone selects a file from the Files list box (lstFiles), we need to display the different properties of this file in the labels in the group box. The event that is generated when someone selects from a list box is called “SelectedIndexChanged”. Write this event handler for the Files list box. The code in the handler will look as:

 

    private void lstFiles_SelectedIndexChanged(object sender, System.EventArgs e)

    {

      string fname = lstFiles.SelectedItem.ToString();

      string fullFileName = Path.Combine(currentDirectory,fname);

      FileInfo finfo = new FileInfo(fullFileName);

      lblFileSize.Text = finfo.Length.ToString();

      lblFileName.Text = finfo.Name;

      lblCreationTime.Text = finfo.CreationTime.ToString();

      lblLastAccessed.Text = finfo.LastAccessTime.ToString();

    }

 

Similarly write an event handler for the Folders list box so that if someone selects a folder from it, the contents of the Files list box are changed appropriately. The SelectedIndexChanged event for the Folders list box will appear as:

 

    private void lstFolders_SelectedIndexChanged(object sender, System.EventArgs e)

    {

      string dirName = lstFolders.SelectedItem.ToString();

      string fullDirName = Path.Combine(

        currentDirectory,dirName);

      ClearAllControls();

      txtDirectory.Text = fullDirName;

      currentDirectory = fullDirName;

      DisplayFiles(fullDirName);

    }

 

Write the following event handler for the “Move Up” button which allows the directory being examined to be changed to the parent directory.

 

    private void btnMoveUp_Click(object sender, System.EventArgs e)

    {

      try

      {

        ClearAllControls();

        string parentDir = new FileInfo(currentDirectory).DirectoryName; // returns parent

        txtDirectory.Text = parentDir;

        currentDirectory = parentDir;

        DisplayFiles(parentDir);

      }

      catch (Exception ex)

      {

        MessageBox.Show(ex.Message);

      }

    }

 

The handler for the exit button will have the code of:

         Application.Exit( );

 

Build and test the application.

 

Enhancing the Application:

     Add three more labels with border style of “Fixed Single” in the right hand portion of the group box as shown above.  Assign names of lblDirCreationTime, lblDirLastAccessed, and lblDirLastWriteTime to the three labels. Add three more labels next to these with default names. The text properties of the labels will be as shown above.

 

Exercise: Modify the code in the DisplayFiles( ) function so that it displays the attributes of the directory selected in the three labels just created. If you are unable to accomplish this, the solution is given at the end of this handout.

 

Exercise: Write the code for the Filter List button event handler, so that it lists only the files in the list box (lstFiles) whose extension matches the text in the txtFilter text box. If you are unable to accomplish this, the solution is given at the end of this handout.

 

 

Deleting a File:

         The File class has a simple Delete method that can be called to delete a file. It is always a good idea to confirm the deletion of a file from the user before actually deleting the file. Place a button at the left bottom of the form (below the group box) with a text property of “Delete Selected File” and a name of btnDeleteFile. Type the following code for the delete file button handler.

 

    private void btnDeleteFile_Click(object sender, System.EventArgs e)

    {

      try

      {

        string selFile = lstFiles.SelectedItem.ToString();

        string selFileFullName =

          Path.Combine(currentDirectory,selFile);

        string question = "Really Delete File? "+

          selFileFullName;

        if (MessageBox.Show(question,"Delete File?",

          MessageBoxButtons.YesNo) == DialogResult.Yes)

        {

          File.Delete(selFileFullName);

          // remove this file from the

          DisplayFiles(currentDirectory);

        }

      }

      catch(Exception ex)

      {

        MessageBox.Show("Unable to Delete File:" + ex.Message);

      }

    }

 

 

Moving a File:

         The File class has a Move method that takes the source file name and the destination file name as parameters.   It is always a good idea to confirm the moving of a file from the user before actually moving the file. Place a button a text box at the middle bottom of the form (below the group box) with a name property of “txtMoveFile”. Place a button next to it with the text property of “Move Selected File” and a name of btnMoveFile. Write the following code for the move file button handler.

    private void btnMoveFile_Click(object sender, System.EventArgs e)

    {

      try

      {

        string selFile = lstFiles.SelectedItem.ToString();

        string selFileFullName =

          Path.Combine(currentDirectory,selFile);

        string question = "Really Move File? "+

          selFileFullName;

        if (MessageBox.Show(question,"Move File?",

          MessageBoxButtons.YesNo) == DialogResult.Yes)

        {

          string destFolder = txtDestFolder.Text;

          DirectoryInfo dir = new DirectoryInfo(destFolder);

          if (!dir.Exists)

           throw new DirectoryNotFoundException

                ("Dest. directory does not exist:"+dir.FullName.ToString());

          string destFileName =

           Path.Combine(destFolder,selFile);

 

          File.Move(selFileFullName,destFileName);

          // refresh the list box

          DisplayFiles(currentDirectory);

        }

      }

      catch(Exception ex)

      {

        MessageBox.Show("Unable to Move File:" + ex.Message);

      }

    }

 

 

Copying a File:

         The File class also contains a Copy method that allows you to copy one file to another file.

Exercise: Add another button to the form with a text property of “Copy Selected File” and a name of btnCopyFile. The same txtDestFolder text box can be used to specify the destination folder for copying the file. The code for the Copy File button handler will be very similar to the Move File handler. The solution to this exercise is given at the end of this handout.

 

The final form of the application is shown below.

 

 

 

 

Reading Writing to Files

 

         The important concept in reading and writing to files is that the file I/O is done using streams. .Net has many different kinds of stream classes that allow you to read/write to files, network sockets, and memory.

 

         Of these, the Stream class is an abstract class that provides binary reading and writing of data. Some of the important methods of the stream class are: Read(), Write(), Close() and Flush().

Example: Binary copying of files.

Create a new C# console type application. Name the project BinaryFileCopy. Name the default class StreamTest. Include the following using statement close to the top of the code area.

     Using System.IO;

Type the following code in the main method.

    static void Main(string[] args)

    {

      int buffSize = 4096;

      Stream inStream = File.OpenRead(@"c:\temp\default.asp");

      Stream outStream = File.Open(@"d:\temp\default.asp",FileMode.OpenOrCreate);

 

      Byte[] buffer = new Byte[buffSize] ;  // buffer size

      int numBytesRead;

      while ((numBytesRead = inStream.Read(buffer,0,buffSize)) > 0)

      {

        outStream.Write(buffer,0,numBytesRead);

      }

 

      inStream.Close();

      outStream.Close();

    }

 

Build and test the program.

 

Buffered Streams:

         Since the disk access is time consuming, the operating system reads the disk in blocks of bytes (even though you may be interested in reading only one byte). Thus when you have large amount of data to read in small chunks at a time, you can create a buffered stream on top of the regular stream so that your next read will come from the buffer, thereby improving the performance of your application greatly.

 

         When writing to a file using buffered stream, you should always flush the buffer before closing the stream otherwise the bytes left in the buffer may not be written to the file.

 

Example: We will modify the previous example to work with buffered streams.

The modifications in the previous code are shown below in bold.

 

    static void Main(string[] args)

    {

      int buffSize = 4096;

      Stream inStream = File.OpenRead(@"c:\temp\default.asp");

      Stream outStream = File.Open(@"d:\temp\default.asp",FileMode.OpenOrCreate);

 

      BufferedStream inbuffStream =

        new BufferedStream(inStream);

      BufferedStream outbuffStream =

        new BufferedStream(outStream);

 

      Byte[] buffer = new Byte[buffSize] ;  // buffer size

      int numBytesRead;

      while ((numBytesRead = inbuffStream.Read(buffer,0,buffSize)) > 0)

      {

        outbuffStream.Write(buffer,0,numBytesRead);

      }

 

      outbuffStream.Flush();

      inbuffStream.Close();

      outbuffStream.Close();

 

    }

 

 

         There is a FileStream class that also supports binary reads and writes. It includes random access capability for reading/writing to files and also supports asynchronous access where the call to the Read or Write methods does not block. This way the user does not need to create any threads for long read/write operations. The asynchronous read/write will notify the program when the operation is completed.

 

Examples:

      FileStream fsw = new FileStream(@"d:\temp\t1.txt", FileMode.Create, FileAccess.Write);

      byte b1 = 65;

      fsw.Write(b1);

 

      // you can also write a array of bytes

      byte [] bArr = new Byte[100];

      fsw.Write(bArr,0,50);

 

      // similarly you can read bytes from a file

      FileStream fsr = new FileStream(@"d:\temp\t1.txt", FileMode.Open, FileAccess.Read);

      fsr.Read(bArr,0,50);

      fsr.Close();

      fsw.Close();

 

Reading and Writing to Text Files:

         For reading and writing to Text files, generally the StreamReader and StreamWriter classes are used. These classes have ReadLine( ) and WriteLine( ) methods that can read or write an entire line of text from the file. You can further parse this line if you needed to read the specific type of data contained in the file.

 

         Another benefit of the StreamReader and StreamWriter classes is that you do not have to worry about the type of character encoding used in the file. The Windows 9x operating system uses ASCII encoded text files whereas in WindowsXP and 2000, Unicode encoding is used. You can also specify or find out the encoding used in a file with the StreamReader or StreamWriter classes.

e.g.,

StreamWriter fsw = new StreamWriter(

@"c:\temp\t2.txt", false, System.Text.Encoding.Unicode);

 

Example: Create a console type application called FileIO. Modify the default class in it to look as:

using System;

using System.IO;  // for file related classes

namespace FileIO

{

      /// <summary>

      /// Summary description for Class1.

      /// </summary>

      class Class1

      {

            /// <summary>

            /// The main entry point for the application.

            /// </summary>

            [STAThread]

            static void Main(string[] args)

            {

                  FileInfo fr = new FileInfo(@"c:\temp\t1.txt"); // input file

                  StreamReader reader = fr.OpenText();  // OpenText returns StreamReader

                  string sline; string [] substrings;

                  char [] separators = {' ', ',','\t'};

                  string name; int ID; float gpa;                    // data for one line

                                                                                    // e.g., Baker  35792  3.45

                  StreamWriter writer = new StreamWriter(@"c:\temp\t2.txt",false);

                                    // false means do not append to existing file

                  sline = reader.ReadLine();

                  while (sline != null)

                  {                              

                        substrings = sline.Split(separators,3); // 3 maximum size to split

                        name = substrings[0];

                        ID = int.Parse(substrings[1]);

                        gpa = float.Parse(substrings[2]);

                        Console.WriteLine("{0} {1} {2}", name,ID,gpa);

                        writer.WriteLine("{0} {1} {2}",name, ID, gpa);

                        sline = reader.ReadLine();

                  }

                  writer.Flush();

                  writer.Close();

            }

      }

}

 

To test the above program, first create a file using notepad called “t1.txt” in the c:\temp directory. The data in this file will look as:

 

Baker         35762    3.35

Simpson    45928    2.89

Kim           87231    3.77

 

 

Solution to Exercises:

 

Clearing All Controls (except fixed labels and top edit box):

    private void ClearAllControls()

    { 

      // instead explicitly clearing a control by

      // its name, it is better to do it through

      // forms collection. This way, if you added

      // a control in the future, it will get cleared.

      foreach (Control ctl in this.Controls)

      {

        string ctlName = ctl.Name;

        string ctlPrefix = ctlName.Substring(0,3); // for lbl

 

        if ((ctl is TextBox) && (ctlName != "txtDirectory"))

        {  // if it is not the top directory textbox

          TextBox txtT1 = (TextBox) ctl;

          txtT1.Text = "";

        }

        if (ctlPrefix == "lbl")  // output labels

        {

          Label L1 = (Label) ctl;

          L1.Text = "";

        }

        if (ctl is ListBox)

        {

          ListBox Lb = (ListBox) ctl;

          Lb.Items.Clear();

        }

 

        // group box is a control container

        // so we need to look inside the group

        if (ctlPrefix == "gro")

        {

          foreach (Control ct in ctl.Controls)

          {

            string ctPrefix = ct.Name.Substring(0,3);

            if (ctPrefix == "lbl")

            {

              Label lb = (Label) ct;

              lb.Text = "";

            }

          }

        }

      }

 

 

Displaying Selected Directory Attributes:

Add the bolded lines to the DisplayFiles function

 

    private void DisplayFiles(string dirName)

    {

      // test to see if directory exists

      DirectoryInfo dir = new DirectoryInfo(dirName);

      if (!dir.Exists)

        throw new DirectoryNotFoundException

          ("directory does not exist:"+dirName);

      // fill the directory listbox

      lstFolders.Items.Clear();

      foreach(DirectoryInfo di in dir.GetDirectories())

        lstFolders.Items.Add(di.Name);

 

      // fill the directory properties labels in the group box

      lblDirCreationTime.Text = dir.CreationTime.ToString();

      lblDirLastAccessed.Text = dir.LastAccessTime.ToString();

      lblDirLastWriteTime.Text = dir.LastWriteTime.ToString();

     

      // fill the Files listbox

      lstFiles.Items.Clear();

      foreach(FileInfo fi in dir.GetFiles())

        lstFiles.Items.Add(fi.Name);

    }

 

Filtering Files of a certain Extension:

Code for the Filter List Button:

 

    private void btnFilter_Click(object sender, System.EventArgs e)

    {

      try

      {

        string filter = “.” + txtFilter.Text;

        lstFiles.Items.Clear(); // clear Files list box

        DirectoryInfo dir = new DirectoryInfo(currentDirectory);

                     

        if (!dir.Exists)

          throw new DirectoryNotFoundException

           ("directory does not exist:"+dir.FullName.ToString());

 

        // fill the Files listbox

        foreach(FileInfo fi in dir.GetFiles())

        {

          if (fi.Extension == filter)

           lstFiles.Items.Add(fi.Name);

        }

 

        //clear file info labels in the group box

        lblFileName.Text = "";

        lblFileSize.Text = "";

        lblLastAccessed.Text = "";

        lblCreationTime.Text = "";

      }

      catch (Exception ex)

      {

        MessageBox.Show(ex.Message);

      }

    }

 

Copying a File to another Folder:

  private void btnCopyFile_Click(object sender, System.EventArgs e)

    {

      try

      {

        string selFile = lstFiles.SelectedItem.ToString();

        string selFileFullName =

          Path.Combine(currentDirectory,selFile);

        string question = "Really Copy File? "+

          selFileFullName;

        if (MessageBox.Show(question,"Copy File?",

          MessageBoxButtons.YesNo) == DialogResult.Yes)

        {

          string destFolder = txtDestFolder.Text;

          DirectoryInfo dir = new DirectoryInfo(destFolder);

          if (!dir.Exists)

            throw new DirectoryNotFoundException

                ("Dest. directory does not exist:"+dir.FullName.ToString());

          string destFileName =

            Path.Combine(destFolder,selFile);

 

          File.Copy(selFileFullName,destFileName);

          // refresh the list box

          DisplayFiles(currentDirectory);

        }

      }

      catch(Exception ex)

      {

        MessageBox.Show("Unable to Copy File:" + ex.Message);

      }

    }