File
and Directory
Files are organized in directories (also called folders). 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 discussed techniques for writing to and reading from files in previous sections.
Figure 17.11 lists several of class File
’s static
methods for manipulating and determining information about files. We demonstrate several of these methods in Fig. 17.13.
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/directory was created. |
GetLastAccessTime |
Returns a DateTime object representing when the file/directory was last accessed. |
GetLastWriteTime |
Returns a DateTime object representing when the file/directory 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 write FileStream associated with the specified file. |
Class Directory
provides capabilities for manipulating directories. Figure 17.12 lists some of class Directory
’s static
methods for directory manipulation. Figure 17.13 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
.
Directory
class static
methods.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. |
File
and Directory
Class FileTestForm
(Fig. 17.13) uses File
and Directory
methods to access file and directory information. The Form
contains the 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 inputTextBox_KeyDown
(lines 19–76). If the user presses the Enter key (line 22), 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 31 invokes private
method GetInformation
(lines 80–101), which calls File
methods GetCreationTime
(line 89), GetLastWriteTime
(line 94) and GetLastAccessTime
(line 99) to access file information. When method GetInformation
returns, line 37 instantiates a StreamReader
for reading text from the file. The StreamReader
constructor takes as an argument a string
containing the name and path 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
. Once the file has been read, the using
block disposes of the corresponding object, which closes the file.
If line 28 determines that the user-specified text is not a file, line 50 determines whether it’s a directory using Directory
method Exists
. If the user specified an existing directory, line 54 invokes method GetInformation
to access the directory information. Lines 57–58 call Directory
method GetDirectories
to obtain a string
array containing the names of the subdirectories in the specified directory. Lines 63–66 display each element in the string
array. Note that, if line 50 determines that the user-specified text is not a directory name, lines 71–73 notify the user that the name the user entered does not exist as a file or directory.
We now consider another example that uses file- and directory-manipulation capabilities. Class LINQToFileDirectoryForm
(Fig. 17.14) uses LINQ with classes File
, Path
and Directory
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” utility—when it finds 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. This example also uses LINQ to Objects to help delete the backup files.
When the user clicks Search Directory, the program invokes searchButton_Click
(lines 23–62), which searches recursively through the directory path specified by the user. If the user inputs text in the TextBox
, line 27 calls Directory
method Exists
to determine whether that text is a valid directory. If it’s not, lines 30–31 notify the user of the error.
SearchDirectory
Lines 36–38 get the current directory (if the user did not specify a path) or the specified directory. Line 46 passes the directory name to recursive method SearchDirectory
(lines 65–95). Line 68 calls Directory
method GetFiles
to get a string
array containing filenames in the specified directory. Line 71 calls Directory
method GetDirectories
to get a string
array containing the subdirectory names in the specified directory.
Lines 74–76 use LINQ to get the filename extensions in the files
array. Path
method GetExtension
obtains the extension for the specified filename. We use the LINQ group by
clause to group the results by filename extension. For each filename-extension group returned by the LINQ query, lines 78–88 use LINQ method Count
to determine the number of occurrences of that extension in the files
array.
Class LINQToFileDirectoryForm
uses a Dictionary
(declared in line 14) to store each filename extension and the corresponding number of filenames with that extension. A Dictionary
(namespace System.Collections.Generic
) is a collection of key–value pairs, in which each key has a corresponding value. Class Dictionary
is a generic class like class List
(presented in Section 9.4). Line 14 indicates that the Dictionary
found
contains pairs of string
s and int
s, which represent the filename extensions and the number of files with those extensions, respectively. Line 80 uses Dictionary
method ContainsKey
to determine whether the specified filename extension has been placed in the Dictionary
previously. If this method returns true
, line 82 adds the count of the number of files with a given extention to the current total for that extension that’s stored in the Dictionary
. Otherwise, line 86 inserts a new key–value pair into the Dictionary
for the new filename extension and its extension count. Lines 91–94 recursively call SearchDirectory
for each subdirectory in the current directory—depending on the number of files and folders, this operation could take substantial time to complete.
CleanDirectory
When method SearchDirectory
returns, line 49 calls CleanDirectory
(lines 98–139) to search for all files with extension .bak
. Lines 101 and 104 obtain the list of filenames and list of directory names in the current directory, respectively. The LINQ query in lines 107–110 locates all filenames in the current directory that have the .bak
extension. Lines 113–132 iterate through the results and ask the user whether each file should be deleted. If the user clicks Yes in the dialog, line 123 uses File
method Delete
to remove the file from disk, and line 124 subtracts 1 from the total number of .bak
files. If the number of .bak
files remaining is 0
, line 129 uses Dictionary
method Remove
to delete the key–value pair for .bak
files from the Dictionary
. Lines 135–138 recursively call CleanDirectory
for each subdirectory in the current directory. After each subdirectory has been checked for .bak
files, method CleanDirectory
returns, and lines 52–58 display the summary of filename extensions and the number of files with each extension. Line 52 uses Dictionary
property Keys
to get all the keys. Line 56 uses the Dictionary
’s indexer to get the value for the current key. Finally, line 60 uses Dictionary
method Clear
to delete the contents of the Dictionary
.