Previous Section  < Day Day Up >  Next Section

5.9. System.IO: Directories and Files

The System.IO namespace includes a set of system-related classes that are used to manage files and directories. Figure 5-9 shows a hierarchy of the most useful classes. Directory and DirectoryInfo contain members to create, delete, and query directories. The only significant difference in the two is that you use Directory with static methods, whereas a DirectoryInfo object must be created to use instance methods. In a parallel manner, File and FileInfo provide static and instance methods for working with files.

Figure 5-9. Directory and File classes in the System.IO namespace


The FileSystemInfo class is a base class for DirectoryInfo and FileInfo. It defines a range of members that are used primarily to provide information about a file or directory. The abstract FileSystemInfo class takes advantage of the fact that files and directories share common features. Its properties include CreationTime, LastAccessTime, LastWriteTime, Name, and FullName. It also includes two important methods: Delete to delete a file or directory and Refresh that updates the latest file and directory information.

Here is a quick look at some of the FileSystemInfo members using DirectoryInfo and FileInfo objects. Note the use of the Refresh method before checking the directory and file attributes.

// DirectoryInfo

string dir  = @"c:\artists";

DirectoryInfo di = new DirectoryInfo(dir);


DateTime IODate = di.CreationTime;

Console.WriteLine("{0:d}",IODate)           // 10/9/2001

// FileInfo

string file = @"C:\artists\manet.jpg";

FileInfo fi = new FileInfo(file);

if (fi.Exists) {


   IODate = fi.CreationTime;

   Console.WriteLine("{0:d}",IODate);       // 5/15/2004

   Console.WriteLine(fi.Name);              // monet.txt

   Console.WriteLine(fi.Extension);         // .txt

   FileAttributes attrib = fi.Attributes;

   Console.WriteLine((int) attrib);         // 32

   Console.WriteLine(attrib);               // Archive


Working with Directories Using the DirectoryInfo, Directory, and Path Classes

When working with directories, you usually have a choice between using the instance methods of DirectoryInfo or the corresponding static methods of Directory. As a rule, if you are going to refer to a directory in several operations, use an instance of DirectoryInfo. Table 5-13 provides a comparison summary of the available methods.

Table 5-13. Comparison of Selected DirectoryInfo and Directory Members









Create a directory or subdirectory.


Pass the string path to the method. Failure results in an exception.


Delete a directory.


Delete(string, bool)

First version deletes an empty directory. Second version deletes a directory and all subdirectories if boolean value is true.


Returns an array of DirectoryInfo type containing all subdirectories in the current directory.



  string filter)

Returns a string array containing the names of directories in the path. A filter may be used to specify directory names.


Returns an array of FileInfo types containing all files in the directory.


GetFiles(string, filter)

Returns string array of files in directory. A filter may be used to match against file names. The filter may contain wildcard characters ? or * to match a single character or zero or more characters.


Retrieves parent directory of current path.


Retrieves parent directory of specified path.



Returns string containing logical drives on system. Format:


Let's look at some examples using both static and instance methods to manipulate and list directory members. The sample code assumes the directory structure shown in Figure 5-10.

Figure 5-10. Directory structure used in Directory examples

Create a Subdirectory

This code adds a subdirectory named cubists below expressionists:

// Directory static method to create directory

string newPath =


if (!Directory.Exists(newPath))


// DirectoryInfo

string curPath= @"c:\artists\expressionists";

di = new DirectoryInfo(curPath);

if (di.Exists) di.CreateSubdirectory(newPath);

Delete a Subdirectory

This code deletes the cubists subdirectory just created:

string newPath = @"c:\artists\expressionists\cubists";

// Directory

if (Directory.Exists(newPath)) Directory.Delete(newPath);

// The following fails because the directory still contains files


// The following succeeds because true is passed to the method


// DirectoryInfo

DirectoryInfo di = new DirectoryInfo(newPath);

If (di.Exists) di.Delete();

List Directories and Files

This code defines a method that recursively loops through and lists the subdirectories and selected files on the C:\artists path. It uses the static Directory methods GeTDirectories and GetFiles. Both of these return string values.

static readonly int Depth=4; // Specify directory level to search

ShowDir (@"c:\artists\", 0); // Call method to list files

// Display directories and files using recursion

public static void ShowDir(string sourceDir, int recursionLvl)


   if (recursionLvl<= Depth) // Limit subdirectory search depth


      // Process the list of files found in the directory


      foreach( string fileName in



         Console.WriteLine("  "+Path.GetFileName(fileName));

      // Use recursion to process subdirectories

      foreach(string subDir in


         ShowDir(subDir,recursionLvl+1);  // Recursive call



GetFiles returns a full path name. The static Path.GetFileName method is used to extract the file name and extension from the path. For demonstration purposes, a filter has been added to the GetFiles method to have it return only the path of files that begins with s.

Here is the same operation using the DirectoryInfo class. Its Getdirectories and GetFiles methods behave differently than the Directory versions: They return objects rather than strings, and they return the immediate directory or file name rather than the entire path.

// DirectoryInfo

public static void ShowDir(DirectoryInfo sourceDir,

                           int recursionLvl)


   if (recursionLvl<= Depth)  // Limit subdirectory search depth


      // Process the list of files found in the directory


      foreach( FileInfo fileName in


         Console.WriteLine("  "+fileName);

      // Use recursion to process subdirectories

      foreach(DirectoryInfo subDir in sourceDir.GetDirectories())

         ShowDir2(subDir,recursionLvl+1);  // Recursive call



The method is called with two parameters: a DirectoryInfo object that encapsulates the path and an initial depth of 0.

DirectoryInfo dirInfo = new DirectoryInfo(@"c:\artists\");

ShowDir(dirInfo, 0);

Using the Path Class to Operate on Path Names

To eliminate the need for developers to create code that manipulates a path string, .NET provides a Path class that consists of static methods designed to operate on a path string. The methods梐 shortcut for Regex patterns梕xtract selected parts of a path or return a boolean value indicating whether the path satisfies some criterion. Note that because the format of a path is platform dependent (a Linux path is specified differently than a Windows path), the .NET implementation of this class is tailored to the platform on which it runs.

To illustrate the static Path methods, let's look at the results of applying selected methods to this path:

string fullPath = @"c:\artists\impressionists\monet.htm";















Working with Files Using the FileInfo and File Classes

The FileInfo and File classes are used for two purposes: to provide descriptive information about a file and to perform basic file operations. The classes include methods to copy, move, and delete files, as well as open files for reading and writing. This short segment uses a FileInfo object to display a file's properties, and the static File.Copy method to copy a file:

string fname= @"c:\artists\impressionists\degas.txt";

// Using the FileInfo class to print file information

FileInfo fi = new FileInfo(fname);  // Create FileInfo object

if (fi.Exists)


   Console.Write("Length: {0}\nName: {1}\nDirectory: {2}",

   fi.Length, fi.Name, fi.DirectoryName);

   // output: --> 488  degas.txt  c:\artists\impressionists


// Use File class to copy a file to another directory

if (File.Exists(fname))




      // Exception is thrown if file exists in target directory

      // (source, destination, overwrite=false)



   catch(Exception ex)





Using FileInfo and File to Open Files

The File and FileInfo classes offer an alternative to creating FileStream, StreamWriter, and StreamReader objects directly. Table 5-14 summarizes the FileInfo methods used to open a file. The static File methods are identical except that their first parameter is always a string containing the name or path of the file to open.

Table 5-14. Selected FileInfo Methods for Opening a File








Opens a file with access and sharing privileges. The three overloads take FileMode, FileAccess, and FileShare enumerations.



Creates a file and returns a FileStream object. If file exists, returns reference to it.



Opens the file in read mode.



Opens a file in write mode.



Opens the file in append mode. If file does not exist, it is created. Equivalent to StreamWriter(string, true).



Opens a file for writing. If the file exists, its contents are overwritten. Equivalent to StreamWriter(string, false).



Opens the file in read mode. Equivalent to StreamReader(string).

The FileInfo.Open method is the generic and most flexible way to open a file:

public FileStream Open(FileMode mode, FileAccess access,

                       FileShare share)

Create, OpenRead, and OpenWrite are specific cases of Open that offer an easy-to-use method that returns a FileStream object and requires no parameters. Similarly, the OpenText, AppendText, and CreateText methods return a StreamReader or StreamWriter object.

The decision to create a FileStream (or StreamReader/StreamWriter) using FileInfo or the FileStream constructor should be based on how the underlying file is used in the application. If the file is being opened for a single purpose, such as for input by a StreamReader, creating a FileStream directly is the best approach. If multiple operations are required on the file, a FileInfo object is better. This example illustrates the advantages of using FileInfo. First, it creates a FileStream that is used for writing to a file; then, another FileStream is created to read the file's contents; finally, FileInfo.Delete is used to delete the file.

FileInfo     fi = new FileInfo(@"c:\temp.txt");

FileStream   fs = fi.Create();          // Create file

StreamWriter sw= new StreamWriter(fs);  // Create StreamWriter

sw.Write("With my crossbow\nI shot the Albatross. ");

sw.Close();                   // Close StreamWriter

// Now use fi to create a StreamReader

fs = fi.OpenRead();           // Open for reading

StreamReader sr = new StreamReader(fs);

while(( string l = sr.ReadLine())!= null)


   Console.WriteLine(l);      // --> With my crossbow

}                             // --> I shot the Albatross.



fi.Delete();                  // Delete temporary file

    Previous Section  < Day Day Up >  Next Section