Classes File and Directory

Information is stored in files, which are organized in directories. Classes File and Directory enable programs to manipulate files and directories on disk. Class File can determine information about files and can be used to open files for reading or writing. We discuss techniques for writing to and reading from files in subsequent sections.

Figure 18.3 lists several of class File's static methods for manipulating and determining information about files. We demonstrate several of these methods in Fig. 18.5.

Figure 18.3. File class static methods (partial list).

static Method

Description

AppendText

Returns a StreamWriter that appends text to an existing file or creates a file if one does not exist.

Copy

Copies a file to a new file.

Create

Creates a file and returns its associated FileStream.

CreateText

Creates a text file and returns its associated StreamWriter.

Delete

Deletes the specified file.

Exists

Returns true if the specified file exists and false otherwise.

GetCreationTime

Returns a DateTime object representing when the file was created.

GetLastAccessTime

Returns a DateTime object representing when the file was last accessed.

GetLastWriteTime

Returns a DateTime object representing when the file was last modified.

Move

Moves the specified file to a specified location.

Open

Returns a FileStream associated with the specified file and equipped with the specified read/write permissions.

OpenRead

Returns a read-only FileStream associated with the specified file.

OpenText

Returns a StreamReader associated with the specified file.

OpenWrite

Returns a read/write FileStream associated with the specified file.

Figure 18.4. Directory class static methods.

(This item is displayed on pages 883 - 884 in the print version)

static Method

Description

CreateDirectory

Creates a directory and returns its associated DirectoryInfo object.

Delete

Deletes the specified directory.

Exists

Returns true if the specified directory exists and false otherwise.

Getdirectories

Returns a string array containing the names of the subdirectories in the specified directory.

GetFiles

Returns a string array containing the names of the files in the specified directory.

GetCreationTime

Returns a DateTime object representing when the directory was created.

GetLastAccessTime

Returns a DateTime object representing when the directory was last accessed.

GetLastWriteTime

Returns a DateTime object representing when items were last written to the directory.

Move

Moves the specified directory to a specified location.

 

Figure 18.5. Testing classes File and Directory.

(This item is displayed on pages 884 - 886 in the print version)

1 // Fig 18.5: FileTestForm.cs 2 // Using classes File and Directory. 3 using System; 4 using System.Windows.Forms; 5 using System.IO; 6 7 // displays contents of files and directories 8 public partial class FileTestForm : Form 9 { 10 // parameterless constructor 11 public FileTestForm() 12 { 13 InitializeComponent(); 14 } // end constructor 15 16 // invoked when user presses key 17 private void inputTextBox_KeyDown( object sender, KeyEventArgs e ) 18 { 19 // determine whether user pressed Enter key 20 if ( e.KeyCode == Keys.Enter ) 21 { 22 string fileName; // name of file or directory 23 24 // get user-specified file or directory 25 fileName = inputTextBox.Text; 26 27 // determine whether fileName is a file 28 if ( File.Exists( fileName ) ) 29 { 30 // get file's creation date, 31 // modification date, etc. 32 outputTextBox.Text = GetInformation( fileName ); 33 34 // display file contents through StreamReader 35 try 36 { 37 // obtain reader and file contents 38 StreamReader stream = new StreamReader( fileName ); 39 outputTextBox.Text += stream.ReadToEnd(); 40 } // end try 41 // handle exception if StreamReader is unavailable 42 catch ( IOException ) 43 { 44 MessageBox.Show( "Error reading from file", "File Error", 45 MessageBoxButtons.OK, MessageBoxIcon.Error ); 46 } // end catch 47 } // end if 48 // determine whether fileName is a directory 49 else if ( Directory.Exists( fileName ) ) 50 { 51 string[] directoryList; // array for directories 52 53 // get directory's creation date, 54 // modification date, etc. 55 outputTextBox.Text = GetInformation( fileName ); 56 57 // obtain file/directory list of specified directory 58 directoryList = Directory.GetDirectories( fileName ); 59 60 outputTextBox.Text += " Directory contents: "; 61 62 // output directoryList contents 63 for ( int i = 0; i < directoryList.Length; i++ ) 64 outputTextBox.Text += directoryList[ i ] + " "; 65 } // end else if 66 else 67 { 68 // notify user that neither file nor directory exists 69 MessageBox.Show( inputTextBox.Text + 70 " does not exist", "File Error", 71 MessageBoxButtons.OK, MessageBoxIcon.Error ); 72 } // end else 73 } // end if 74 } // end method inputTextBox_KeyDown 75 76 // get information on file or directory 77 private string GetInformation( string fileName ) 78 { 79 string information; 80 81 // output that file or directory exists 82 information = fileName + " exists "; 83 84 // output when file or directory was created 85 information += "Created: " + 86 File.GetCreationTime( fileName ) + " "; 87 88 // output when file or directory was last modified 89 information += "Last modified: " + 90 File.GetLastWriteTime( fileName ) + " "; 91 92 // output when file or directory was last accessed 93 information += "Last accessed: " + 94 File.GetLastAccessTime( fileName ) + " " + " "; 95 96 return information; 97 } // end method GetInformation 98 } // end class FileTestForm

(a)

(b)

(c)

(d)

Class Directory provides capabilities for manipulating directories. Figure 18.4 lists some of class Directory's static methods for directory manipulation. Figure 18.5 demonstrates several of these methods, as well. The DirectoryInfo object returned by method CreateDirectory contains information about a directory. Much of the information contained in class DirectoryInfo also can be accessed via the methods of class Directory.

Demonstrating Classes File and Directory

Class FileTestForm (Fig. 18.5) uses File and Directory methods to access file and directory information. This Form contains the control inputTextBox, in which the user enters a file or directory name. For each key that the user presses while typing in the TextBox, the program calls event handler inputTextBox_KeyDown (lines 1774). If the user presses the Enter key (line 20), this method displays either the file's or directory's contents, depending on the text the user input. (If the user does not press the Enter key, this method returns without displaying any content.) Line 28 uses File method Exists to determine whether the user-specified text is the name of an existing file. If so, line 32 invokes private method GetInformation (lines 7797), which calls File methods GetCreationTime (line 86), GetLastWriteTime (line 90) and GetLastAccessTime (line 94) to access file information. When method GetInformation returns, line 38 instantiates a StreamReader for reading text from the file. The StreamReader constructor takes as an argument a string containing the name of the file to open. Line 39 calls StreamReader method ReadToEnd to read the entire contents of the file as a string, then appends the string to outputTextBox.

If line 28 determines that the user-specified text is not a file, line 49 determines whether it is a directory using Directory method Exists. If the user specified an existing directory, line 55 invokes method GetInformation to access the directory information. Line 58 calls Directory method Getdirectories to obtain a string array containing the names of subdirectories in the specified directory. Lines 6364 display each element in the string array. Note that, if line 49 determines that the user-specified text is not a directory name, lines 6971 notify the user (via a MessageBox) that the name the user entered does not exist as a file or directory.

Finding Directories with Regular Expressions

We now consider another example that uses C#'s file- and directory-manipulation capabilities. Class FileSearchForm (Fig. 18.6) uses classes File and Directory, and regular expression capabilities, to report the number of files of each file type that exist in the specified directory path. The program also serves as a "clean-up" utilitywhen the program encounters a file that has the .bak filename extension (i.e., a backup file), the program displays a MessageBox asking the user whether that file should be removed, then responds appropriately to the user's input.

Figure 18.6. Regular expression used to determine file types.

1 // Fig 18.6: FileSearchForm.cs 2 // Using regular expressions to determine file types. 3 using System; 4 using System.Windows.Forms; 5 using System.IO; 6 using System.Text.RegularExpressions; 7 using System.Collections.Specialized; 8 9 // uses regular expressions to determine file types 10 public partial class FileSearchForm : Form 11 { 12 string currentDirectory = Directory.GetCurrentDirectory(); 13 string[] directoryList; // subdirectories 14 string[] fileArray; 15 16 // store extensions found and number found 17 NameValueCollection found = new NameValueCollection(); 18 19 // parameterless constructor 20 public FileSearchForm() 21 { 22 InitializeComponent(); 23 } // end constructor 24 25 // invoked when user types in text box 26 private void inputTextBox_KeyDown( object sender, KeyEventArgs e ) 27 { 28 // determine whether user pressed Enter 29 if ( e.KeyCode == Keys.Enter ) 30 searchButton_Click( sender, e ); 31 } // end method inputTextBox_KeyDown 32 33 // invoked when user clicks "Search Directory" button 34 private void searchButton_Click( object sender, EventArgs e ) 35 { 36 // check for user input; default is current directory 37 if ( inputTextBox.Text != "" ) 38 { 39 // verify that user input is valid directory name 40 if ( Directory.Exists( inputTextBox.Text ) ) 41 { 42 currentDirectory = inputTextBox.Text; 43 44 // reset input text box and update display 45 directoryLabel.Text = "Current Directory:" + 46 " " + currentDirectory; 47 } // end if 48 else 49 { 50 // show error if user does not specify valid directory 51 MessageBox.Show( "Invalid Directory", "Error", 52 MessageBoxButtons.OK, MessageBoxIcon.Error ); 53 } // end else 54 } // end if 55 56 // clear text boxes 57 inputTextBox.Text = ""; 58 outputTextBox.Text = ""; 59 60 SearchDirectory( currentDirectory ); // search directory 61 62 // summarize and print results 63 foreach ( string current in found ) 64 { 65 outputTextBox.Text += "* Found " + 66 found[ current ] + " " + current + " files. "; 67 } // end foreach 68 69 // clear output for new search 70 found.Clear(); 71 } // end method searchButton_Click 72 73 // search directory using regular expression 74 private void SearchDirectory( string currentDirectory ) 75 { 76 // for file name without directory path 77 try 78 { 79 string fileName = ""; 80 81 // regular expression for extensions matching pattern 82 Regex regularExpression = new Regex( 83 @"[a-zA-Z0-9]+.(?w+)" ); 84 85 // stores regular-expression match result 86 Match matchResult; 87 88 string fileExtension; // holds file extensions 89 90 // number of files with given extension in directory 91 int extensionCount; 92 93 // get directories 94 directoryList = Directory.GetDirectories( currentDirectory ); 95 96 // get list of files in current directory 97 fileArray = Directory.GetFiles( currentDirectory ); 98 99 // iterate through list of files 100 foreach ( string myFile in fileArray ) 101 { 102 // remove directory path from file name 103 fileName = myFile.Substring( myFile.LastIndexOf( @"" ) + 1 ); 104 105 // obtain result for regular-expression search 106 matchResult = regularExpression.Match( fileName ); 107 108 // check for match 109 if ( matchResult.Success ) 110 fileExtension = matchResult.Result( "${extension}" ); 111 else 112 fileExtension = "[no extension]"; 113 114 // store value from container 115 if ( found[ fileExtension ] == null ) 116 found.Add( fileExtension, "1" ); 117 else 118 { 119 extensionCount = Int32.Parse( found[ fileExtension ] ) + 1; 120 found[ fileExtension ] = extensionCount.ToString(); 121 } // end else 122 123 // search for backup( .bak ) files 124 if ( fileExtension == "bak" ) 125 { 126 // prompt user to delete ( .bak ) file 127 DialogResult result = 128 MessageBox.Show( "Found backup file " + 129 fileName + ". Delete?", "Delete Backup", 130 MessageBoxButtons.YesNo, MessageBoxIcon.Question ); 131 132 // delete file if user clicked 'yes' 133 if ( result == DialogResult.Yes ) 134 { 135 File.Delete( myFile ); 136 extensionCount = Int32.Parse( found[ "bak" ] ) - 1; 137 found[ "bak" ] = extensionCount.ToString(); 138 } // end if 139 } // end if 140 } // end foreach 141 142 // recursive call to search files in subdirectory 143 foreach ( string myDirectory in directoryList ) 144 SearchDirectory( myDirectory ); 145 } // end try 146 // handle exception if files have unauthorized access 147 catch ( UnauthorizedAccessException ) 148 { 149 MessageBox.Show( "Some files may not be visible" + 150 " due to permission settings", "Warning", 151 MessageBoxButtons.OK, MessageBoxIcon.Information ); 152 } // end catch 153 } // end method SearchDirectory 154 } // end class FileSearchForm

When the user presses the Enter key or clicks the Search Directory button, the program invokes method searchButton_Click (lines 3471), which searches recursively through the directory path that the user provides. If the user inputs text in the TextBox, line 40 calls Directory method Exists to determine whether that text is a valid directory path and name. If not, lines 5152 notify the user of the error.

If the user specifies a valid directory, line 60 passes the directory name as an argument to private method SearchDirectory (lines 74153). This method locates files that match the regular expression defined in lines 8283. This regular expression matches any sequence of numbers or letters followed by a period and one or more letters. Notice the substring of format (?w+) in the argument to the Regex constructor (line 83). This indicates that the part of the string that matches w+ (i.e., the filename extension that appears after a period in the file name) should be placed in the regular expression variable named extension. This variable's value is retrieved later from Match object matchResult to obtain the filename extension so we can summarize the types of files in the directory.

Line 94 calls Directory method Getdirectories to retrieve the names of all subdirectories that belong to the current directory. Line 97 calls Directory method GetFiles to store in string array fileArray the names of files in the current directory. The foreach loop in lines 100140 searches for all files with extension .bak. The loop at lines 143144 then calls SearchDirectory recursively (line 144) for each subdirectory in the current directory. Line 103 eliminates the directory path, so the program can test only the file name when using the regular expression. Line 106 uses Regex method Match to match the regular expression with the file name, then assigns the result to Match object matchResult. If the match is successful, line 110 uses Match method Result to assign to fileExtension the value of the regular expression variable extension from object matchResult. If the match is unsuccessful, line 112 sets fileExtension to "[no extension]".

Class FileSearchForm uses an instance of class NameValueCollection (declared in line 17) to store each filename-extension type and the number of files for each type. A NameValueCollection (namespace System.Collections.Specialized) contains a collection of key-value pairs of strings, and provides method Add to add a key-value pair to the collection. The indexer for this class can index according to the order that the items were added or according to the keys. Line 115 uses NameValueCollection found to determine whether this is the first occurrence of the filename extension (the expression returns null if the collection does not contain a key-value pair for the specified fileExtension). If this is the first occurrence, line 116 adds that extension to found as a key with the value 1. Otherwise, line 119 increments the value associated with the extension in found to indicate another occurrence of that file extension, and line 120 assigns the new value to the key-value pair.

Line 124 determines whether fileExtension equals "bak"i.e., whether the file is a backup file. If so, lines 127130 prompt the user to indicate whether the file should be removed; if the user clicks Yes (line 133), lines 135137 delete the file and decrement the value for the "bak" file type in found.

Lines 143144 call method SearchDirectory for each subdirectory. Using recursion, we ensure that the program performs the same logic for finding .bak files in each subdirectory. After each subdirectory has been checked for .bak files, method SearchDirectory completes, and lines 6367 display the results.

Категории