Input and Output Classes |
A complete PDF version of the text book is now available. The PDF version is an almost complete subset of the HTML version (where only a few, long program listings have been removed). See here. |
The previous chapter was about streams, and as such also about files. In this chapter we will deal with the properties of files beyond reading and writing. File copying, renaming, creation time, existence, and deletion represent a few of these. In addition to files we will also in this chapter discuss directories.
|
38.1. The File and FileInfo classes
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
Two overlapping file-related classes are available to the C# programmer: FileInfo and File. Both classes belong to the namespace System.IO. Objects of class FileInfo represents a single file, created on the basis of the name or path of the file (which is a string). The class File contains static methods for file manipulation. Class File is static, see Section 11.12, and as such there can be no instances of class File. If you intend to write object-oriented programs with file manipulation needs it is recommended that you represent files as instances of class FileInfo.
Let us right away write a program which illustrates how to use instances of class FileInfo for representation of files. All aspects related to class FileInfo is shown in purple in Program 38.1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | using System; using System.IO; public class FileInfoDemo{ public static void Main(){ // Setting up file names string fileName = "file-info.cs", fileNameCopy = "file-info-copy.cs"; // Testing file existence FileInfo fi = new FileInfo(fileName); // this source file Console.WriteLine("{0} does {1} exist", fileName, fi.Exists ? "" : "not"); // Show file info properties: Console.WriteLine("DirectoryName: {0}", fi.DirectoryName); Console.WriteLine("FullName: {0}", fi.FullName); Console.WriteLine("Extension: {0}", fi.Extension); Console.WriteLine("Name: {0}", fi.Name); Console.WriteLine("Length: {0}", fi.Length); Console.WriteLine("CreationTime: {0}", fi.CreationTime); // Copy one file to another fi.CopyTo(fileNameCopy); FileInfo fiCopy = new FileInfo(fileNameCopy); // Does the copy exist? Console.WriteLine("{0} does {1} exist", fileNameCopy, fiCopy.Exists ? "" : "not"); // Delete the copy again fiCopy.Delete(); // Does the copy exist? Console.WriteLine("{0} does {1} exist", fileNameCopy, fiCopy.Exists ? "" : "not"); // !!?? // Create new FileInfo object for the copy FileInfo fiCopy1 = new FileInfo(fileNameCopy); // Check if the copy exists? Console.WriteLine("{0} does {1} exist", fileNameCopy, fiCopy1.Exists ? "" : "not"); // Achieve a TextReader (StreamReader) from the file info object // and echo the first ten lines in the file to standard output using(StreamReader sr = fi.OpenText()){ for (int i = 1; i <= 10; i++) Console.WriteLine(" " + sr.ReadLine()); } } } | |||
|
In line 12 we create a FileInfo object on the source file of the C# program text shown in Program 38.1. In line 13-14 we report on the existence of this file in the file system. (We expect existence, of course). In line 16-22 we access various properties (in the sense of C# properties, see Chapter 18) of the FileInfo object. In line 25 we copy the file, and in line 30 we check the existence of the copy. In line 33 we delete the copy, and in line 37 we check the existence of copy again. Against our intuition, we realize that the copy of the file still exists after its deletion. (See next paragraph for an explanation). If, however, we establish a fresh FileInfo object on the path to the deleted file, we get the expected result. In line 45-50 we use the OpenText method of the FileInfo object to establish a TextReader on the file. Via a number of ReadLine activations in line 49 we demonstrate that we can read the contents of the file.
The file existence problem described above occurs because the instance of class FileInfo and the state of the underlying file system become inconsistent. The instance method Refresh of class FileInfo can be used to update the FileInfo object from the information in the operating system. If you need trustworthy information about your files, you should always call the Refresh operation before you access any FileInfo attribute. If we call fiCopy.Refresh() in line 34, the problem observed in line 37 vanishes.
The output of Program 38.1 is shown in Listing 38.2 (only on web).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | file-info.cs does exist DirectoryName: c:\users\kurt\courses\prog1-06\sources\c-sharp\io\file-info-demo FullName: c:\users\kurt\courses\prog1-06\sources\c-sharp\io\file-info-demo\file-info.cs Extension: .cs Name: file-info.cs Length: 1342 CreationTime: 02-11-2006 21:18:31 file-info-copy.cs does exist file-info-copy.cs does exist file-info-copy.cs does not exist using System; using System.IO; public class FileInfoDemo{ public static void Main(){ string fileName = "file-info.cs", fileNameCopy = "file-info-copy.cs"; FileInfo fi = new FileInfo(fileName); // this source file | |||
|
The following gives an overview of some selected operations in class FileInfo:
|
The parameter of the FileInfo constructor is an absolute or relative path to a file. The file path must be well-formed according to a set of rules described in the class documentation. As examples, the file paths "c:\temp c:\user" and " dir1\dir2\file.dat" are both malformed.
We have also written af version of Program 38.1 in which we use the static class File instead of FileInfo, see Program 38.3. We do not include this program, nor the listing of its output, in the paper edition of the material. We notice that the file existence frustrations in Program 38.1 (of the deleted file) do not appear when we use the static operations of the static class File.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | using System; using System.IO; public class FileDemo{ public static void Main(){ // Setup file names string fileName = "file.cs", // this source file fileNameCopy = "fileCopy.cs"; // Does this source file exist? Console.WriteLine("{0} does {1} exist", fileName, File.Exists(fileName) ? "" : "not"); // Copy this source file File.Copy(fileName, fileNameCopy); // Does the copy exist? Console.WriteLine("{0} does {1} exist", fileNameCopy, File.Exists(fileNameCopy) ? "" : "not"); // Delete the copy again Console.WriteLine("Deleting {0}", fileNameCopy); File.Delete(fileNameCopy); // Does the deleted file exist Console.WriteLine("{0} does {1} exist", fileNameCopy, File.Exists(fileNameCopy) ? "" : "not"); // Read all lines in source file and echo // one of them to the console string[] lines = File.ReadAllLines(fileName); Console.WriteLine("Line {0}: {1}", 6, lines[6]); } } | |||
|
1 2 3 4 5 | file.cs does exist fileCopy.cs does exist Deleting fileCopy.cs fileCopy.cs does not exist Line 6: string fileName = "file.cs", // this source file | |||
|
There is a substantial overlap between the instance methods of
class FileInfo and the static methods in class File |
38.2. The Directory and DirectoryInfo classes
Contents Up Previous Next Slide Annotated slide Aggregated slides Subject index Program index Exercise index
The classes DirectoryInfo and Directory are natural directory counterparts of the classes FileInfo and File, as described in Section 38.1. In this section we will show an example use of class DirectoryInfo, and we will provide an overview of the members in the class. Like for files, an instance of class DirectoryInfo is intended to represent a given directory of the underlying file system. We recommend that you use the class DirectoryInfo, rather than the static class Directory, when you write object-oriented programs.
It is worth noticing that the classes FileInfo and DirectoryInfo have a common abstract, superclass class FileSystemInfo.
Here follows a short program that use an instance of class DirectoryInfo for representation of a given directory from the underlying operating system.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using System.IO; public class DirectoryInfoDemo{ public static void Main(){ string fileName = "directory-info.cs"; // The current source file // Get the DirectoryInfo of the current directory // from the FileInfo of the current source file FileInfo fi = new FileInfo(fileName); // This source file DirectoryInfo di = fi.Directory; Console.WriteLine("File {0} is in directory \n {1}", fi, di); // Get the files and directories in the parent directory. FileInfo[] files = di.Parent.GetFiles(); DirectoryInfo[] dirs = di.Parent.GetDirectories(); // Show the name of files and directories on the console Console.WriteLine("\nListing directory {0}:", di.Parent.Name); foreach(DirectoryInfo d in dirs) Console.WriteLine(d.Name); foreach(FileInfo f in files) Console.WriteLine(f.Name); } } | |||
|
Like in Program 38.3 the starting point in Program 38.5 is a FileInfo object that represents the source file shown in Program 38.5. Based on the FileInfo object, we create a DirectoryInfo object in line 12. This DirectoryInfo object represents the directory in which the actual source file resides. Let us call it the current directory . In line 17 we illustrate the Parent property and the GetFiles method; We create an array, files, of FileInfo object of the parent directory of the current directory. Thus, this array holds all files of the parent of current directory. Similarly, dirs declared in line 18 is assigned to hold all directories of the parent of current directory. We print these files and directories in line 20-25.
The output of Program 38.5 (only on web) is shown in Listing 38.6 (only on web). A similar program, programmed with use of the static operations in class Directory, is shown in Program 38.7 (only on web).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | File directory-info.cs is in directory C:\users\kurt\courses\prog1-06\sources\c-sharp\io\directory-info-demo Listing directory io: console decorator directory-info-demo encoding file-copy file-demo file-info-demo filestream-ex guess-encoding text-writer-reader README | |||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using System.IO; public class DirectoryDemo{ public static void Main(){ string fileName = "directory.cs"; // The current source file FileInfo fi = new FileInfo(fileName); // This source file string thisFile = fi.FullName, thisDir = Directory.GetParent(thisFile).FullName, parentDir = Directory.GetParent(thisDir).FullName; Console.WriteLine("This file: {0}", thisFile); Console.WriteLine("This Directory: {0}", thisDir); Console.WriteLine("Parent directory: {0}", parentDir); string[] files = Directory.GetFiles(parentDir); string[] dirs = Directory.GetDirectories(parentDir); Console.WriteLine("\nListing directory {0}:", parentDir); foreach(string d in dirs) Console.WriteLine(d); foreach(string f in files) Console.WriteLine(f); } } | |||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | This file: C:\users\kurt\courses\prog1-06\sources\c-sharp\io\directory-demo\directory.cs This Directory: C:\users\kurt\courses\prog1-06\sources\c-sharp\io\directory-demo Parent directory: C:\users\kurt\courses\prog1-06\sources\c-sharp\io Listing directory C:\users\kurt\courses\prog1-06\sources\c-sharp\io: C:\users\kurt\courses\prog1-06\sources\c-sharp\io\console C:\users\kurt\courses\prog1-06\sources\c-sharp\io\decorator C:\users\kurt\courses\prog1-06\sources\c-sharp\io\directory-demo C:\users\kurt\courses\prog1-06\sources\c-sharp\io\directory-info-demo C:\users\kurt\courses\prog1-06\sources\c-sharp\io\encoding C:\users\kurt\courses\prog1-06\sources\c-sharp\io\file-copy C:\users\kurt\courses\prog1-06\sources\c-sharp\io\file-demo C:\users\kurt\courses\prog1-06\sources\c-sharp\io\file-info-demo C:\users\kurt\courses\prog1-06\sources\c-sharp\io\filestream-ex C:\users\kurt\courses\prog1-06\sources\c-sharp\io\guess-encoding C:\users\kurt\courses\prog1-06\sources\c-sharp\io\text-writer-reader C:\users\kurt\courses\prog1-06\sources\c-sharp\io\README | |||
|
The following shows an overview of the instance properties and instance methods in class DirectoryInfo:
|
The constructor takes a directory path string as parameter. It is possible to create a DirectoryInfo object on a string that represents a non-existing directory path. Like file paths, the given directory path must be well-formed (according to rules stated in the class documentation).
The downwards directory navigation operations GetDirectories, GetFiles, and GetFileSystemInfo are able to filter their results (with use of strings with wildcards, such as "temp*", which match all files/directories whose names start with "temp"). It is also possible to specify if the operations should access direct files/directories, or if they should access direct as well as indirect file/directories.
As for File and FileInfo, there is substantial overlap between the classes Directory and DirectoryInfo |