![]() |
< Day Day Up > |
![]() |
5.9. System.IO: Directories and FilesThe 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 namespaceFileSystemInfoThe 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); di.Refresh(); 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) { fi.Refresh(); 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 ClassesWhen 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.
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 examplesCreate a SubdirectoryThis code adds a subdirectory named cubists below expressionists: // Directory static method to create directory string newPath = @"c:\artists\expressionists\cubists"; if (!Directory.Exists(newPath)) Directory.CreateDirectory(newPath); // DirectoryInfo string curPath= @"c:\artists\expressionists"; di = new DirectoryInfo(curPath); if (di.Exists) di.CreateSubdirectory(newPath); Delete a SubdirectoryThis 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 Directory.Delete(@"c:\artists\expressionists"); // The following succeeds because true is passed to the method Directory.Delete(@"c:\artists\expressionists",true); // DirectoryInfo DirectoryInfo di = new DirectoryInfo(newPath); If (di.Exists) di.Delete(); List Directories and FilesThis 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 Console.WriteLine(sourceDir); foreach( string fileName in Directory.GetFiles(sourceDir,"s*.*")) { Console.WriteLine(" "+Path.GetFileName(fileName)); // Use recursion to process subdirectories foreach(string subDir in Directory.GetDirectories(sourceDir)) 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 Console.WriteLine(sourceDir.FullName); foreach( FileInfo fileName in sourceDir.GetFiles("s*.*")) 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 NamesTo 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 ClassesThe 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)) { try { // Exception is thrown if file exists in target directory // (source, destination, overwrite=false) File.Copy(fname,@"c:\artists\19thcentury\degas.txt",false); } catch(Exception ex) { Console.Write(ex.Message); } } Using FileInfo and File to Open FilesThe 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.
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. sr.Close(); fs.Close(); fi.Delete(); // Delete temporary file |
![]() |
< Day Day Up > |
![]() |