Section 21.1. Files and Directories


21.1. Files and Directories

Before looking at how you can get data into and out of files, let's start by examining the support provided for file and directory manipulation.

The classes you need are in the System.IO namespace. These include the File class, which represents a file on disk, and the Directory class, which represents a directory (also known in Windows as a folder).

21.1.1. Working with Directories

The Directory class exposes static methods for creating, moving, and exploring directories. All the methods of the Directory class are static, and therefore you can call them all without having an instance of the class.

The DirectoryInfo class is a similar class, but one which has nothing but instance members (i.e., no static members at all). DirectoryInfo derives from FileSystemInfo, which in turn derives from MarshalByRefObject. The FileSystemInfo class has a number of properties and methods that provide information about a file or directory.

Table 21-1 lists the principal methods of the Directory class, and Table 21-2 lists the principal methods of the DirectoryInfo class, including important properties and methods inherited from FileSystemInfo.

Table 21-1. Principal methods of the Directory class

Method

Use

CreateDirectory( )

Creates all directories and subdirectories specified by its path parameter.

GetCreationTime( )

Returns and sets the time the specified directory was created.

GetDirectories( )

Gets named directories.

GetLogicalDrives( )

Returns the names of all the logical drives in the form <drive>:\.

GetFiles( )

Returns the names of files matching a pattern.

GetParent( )

Returns the parent directory for the specified path.

Move( )

Moves a directory and its contents to a specified path.


Table 21-2. Principal methods and properties of the DirectoryInfo class

Method or property

Use

Attributes

Inherits from FileSystemInfo; gets or sets the attributes of the current file.

CreationTime

Inherits from FileSystemInfo; gets or sets the creation time of the current file.

Exists

Public property Boolean value, which is TRue if the directory exists.

Extension

Public property inherited from FileSystemInfo; i.e., the file extension.

FullName

Public property inherited from FileSystemInfo; i.e., the full path of the file or directory.

LastAccessTime

Public property inherited from FileSystemInfo; gets or sets the last access time.

LastWriteTime

Public property inherited from FileSystemInfo; gets or sets the time when the current file or directory was last written to.

Name

Public property name of this instance of DirectoryInfo.

Parent

Public property parent directory of the specified directory.

Root

Public property root portion of the path.

Create( )

Public method that creates a directory.

CreateSubdirectory( )

Public method that creates a subdirectory on the specified path.

Delete( )

Public method that deletes a DirectoryInfo and its contents from the path.

GetDirectories( )

Public method that returns a DirectoryInfo array with subdirectories.

GetFiles( )

Public method that returns a list of files in the directory.

GetFileSystemIn fos( )

Public method that retrieves an array of FileSystemInfo objects.

MoveTo( )

Public method that moves a DirectoryInfo and its contents to a new path.

Refresh( )

Public method inherited from FileSystemInfo; refreshes the state of the object.


21.1.2. Creating a DirectoryInfo Object

To explore a directory hierarchy, you need to instantiate a DirectoryInfo object. The DirectoryInfo class provides methods for getting not just the names of contained files and directories, but also FileInfo and DirectoryInfo objects, allowing you to dive into the hierarchical structure, extracting subdirectories and exploring these recursively.

Instantiate a DirectoryInfo object with the name of the directory you want to explore:

string path = Environment.GetEnvironmentVariable("SystemRoot"); DirectoryInfo dir = new DirectoryInfo(path);

Remember that the @ sign before a string creates a verbatim string literal in which it isn't necessary to escape characters such as the backslash. This was covered in Chapter 10.


You can ask that DirectoryInfo object for information about itself, including its name, full path, attributes, the time it was last accessed, and so forth. To explore the subdirectory hierarchy, ask the current directory for its list of subdirectories:

DirectoryInfo[] directories = dir.GetDirectories();

This returns an array of DirectoryInfo objects, each of which represents a directory. You can then recurse into the same method, passing in each DirectoryInfo object in turn:

foreach (DirectoryInfo newDir in directories) {    dirCounter++;    ExploreDirectory(newDir); }

The dirCounter static int member variable keeps track of how many subdirectories have been found altogether. To make the display more interesting, add a second static int member variable indentLevel that will be incremented each time you recurse into a subdirectory, and will be decremented when you pop out. This will allow you to display the subdirectories indented under the parent directories. The complete listing is shown in Example 21-1.

Example 21-1. Recursing through subdirectories
#region Using directives using System; using System.Collections.Generic; using System.IO; using System.Text; #endregion namespace RecursingDirectories {    class Tester    {       // static member variables to keep track of totals       // and indentation level       static int dirCounter = 1;       static int indentLevel = -1; // so first push = 0       public static void Main( )       {          Tester t = new Tester( );          // choose the initial subdirectory          string theDirectory =             Environment.GetEnvironmentVariable( "SystemRoot" );          // Mono and Shared Source CLI users on Linux, Unix or           // Mac OS X should comment out the preceding two lines          // of code and uncomment the following:          //string theDirectory = "/tmp";          // call the method to explore the directory,          // displaying its access date and all          // subdirectories          DirectoryInfo dir = new DirectoryInfo( theDirectory );          t.ExploreDirectory( dir );          // completed. print the statistics          Console.WriteLine(             "\n\n{0} directories found.\n",             dirCounter );       }       // Set it running with a directoryInfo object       // for each directory it finds, it will call        // itself recursively       private void ExploreDirectory( DirectoryInfo dir )       {          indentLevel++;  // push a directory level          // create indentation for subdirectories          for ( int i = 0; i < indentLevel; i++ )             Console.Write( "  " ); // two spaces per level          // print the directory and the time last accessed          Console.WriteLine( "[{0}] {1} [{2}]\n",             indentLevel, dir.Name, dir.LastAccessTime );          // get all the directories in the current directory          // and call this method recursively on each          DirectoryInfo[] directories = dir.GetDirectories( );          foreach ( DirectoryInfo newDir in directories )          {             dirCounter++;  // increment the counter             ExploreDirectory( newDir );          }          indentLevel--; // pop a directory level       }    } } Output (excerpt):     [2] logiscan [5/1/2001 3:06:41 PM]     [2] miitwain [5/1/2001 3:06:41 PM]   [1] Web [5/1/2001 3:06:41 PM]     [2] printers [5/1/2001 3:06:41 PM]       [3] images [5/1/2001 3:06:41 PM]     [2] Wallpaper [5/1/2001 3:06:41 PM] 363 directories found.

You must add using System.IO; to the top of your file; Visual Studio 2005 doesn't do this automatically.


The program begins by identifying a directory (SystemRoot, usually C:\WinNT or C:\Windows) and creating a DirectoryInfo object for that directory. It then calls ExploreDirectory, passing in that DirectoryInfo object. ExploreDirectory displays information about the directory and then retrieves all the subdirectories.

The list of all the subdirectories of the current directory is obtained by calling Getdirectories. This returns an array of DirectoryInfo objects. ExploreDirectory is the recursive method; each DirectoryInfo object is passed into ExploreDirectory in turn. The effect is to push recursively into each subdirectory, and then pop back out to explore sister directories until all the subdirectories of %SystemRoot% are displayed. When ExploreDirectory finally returns, the calling method prints a summary.

21.1.3. Working with Files

The DirectoryInfo object can also return a collection of all the files in each subdirectory found. The GetFiles( ) method returns an array of FileInfo objects, each of which describes a file in that directory. The FileInfo and File objects relate to one another, much as DirectoryInfo and Directory do. Like the methods of Directory, all the File methods are static; like DirectoryInfo, all the methods of FileInfo are instance methods.

Table 21-3 lists the principal methods of the File class; Table 21-4 lists the important members of the FileInfo class.

Table 21-3. Principal public static methods of the File class

Method

Use

AppendText( )

Creates a StreamWriter that appends text to the specified file.

Copy( )

Copies an existing file to a new file.

Create( )

Creates a file in the specified path.

CreateText( )

Creates a StreamWriter that writes a new text file to the specified file.

Delete( )

Deletes the specified file.

Exists( )

Returns true if the specified file exists.

GetAttributes(), SetAttributes( )

Gets and sets the FileAttributes of the specified file.

GetCreationTime( ), SetCreationTime( )

Returns and sets the creation date and time of the file.

GetLastAccessTime( ), SetLastAccessTime( )

Returns and sets the last time the specified file was accessed.

GetLastWriteTime( ), SetLastWriteTime( )

Returns and sets the last time the specified file was written to.

Move( )

Moves a file to a new location; can be used to rename a file.

OpenRead( )

Public static method that opens a FileStream on the file.

OpenWrite( )

Creates a read/write Stream on the specified path.


Table 21-4. Methods and properties of the FileInfo class

Method or property

Use

Attributes( )

Inherits from FileSystemInfo; gets or sets the attributes of the current file.

CreationTime

Inherits from FileSystemInfo; gets or sets the creation time of the current file.

Directory

Public property that gets an instance of the parent directory.

Exists

Public property Boolean value that is TRue if the directory exists.

Extension

Public property inherited from FileSystemInfo; i.e., the file extension.

FullName

Public property inherited from FileSystemInfo; i.e., the full path of the file or directory.

LastAccessTime

Public property inherited from FileSystemInfo; gets or sets the last access time.

LastWriteTime

Public property inherited from FileSystemInfo; gets or sets the time when the current file or directory was last written to.

Length

Public property that gets the size of the current file.

Name

Public property Name of this DirectoryInfo instance.

AppendText( )

Public method that creates a StreamWriter that appends text to a file.

CopyTo( )

Public method that copies an existing file to a new file.

Create( )

Public method that creates a new file.

Delete( )

Public method that permanently deletes a file.

MoveTo( )

Public method to move a file to a new location; can be used to rename a file.

Open( )

Public method that opens a file with various read/write and sharing privileges.

OpenRead( )

Public method that creates a read-only FileStream.

OpenText()

Public method that creates a StreamReader that reads from an existing text file.

OpenWrite( )

Public method that creates a write-only FileStream.


Example 21-2 modifies Example 21-1, adding code to get a FileInfo object for each file in each subdirectory. That object is used to display the name of the file, along with its length and the date and time it was last accessed.

Example 21-2. Exploring files and subdirectories
#region Using directives using System; using System.Collections.Generic; using System.IO; using System.Text; #endregion namespace ExploringFilesAndSubdirectories {    class Tester    {       // static member variables to keep track of totals       // and indentation level       static int dirCounter = 1;       static int indentLevel = -1; // so first push = 0       static int fileCounter = 0;       public static void Main( )       {          Tester t = new Tester( );          // choose the initial subdirectory          string theDirectory =             Environment.GetEnvironmentVariable( "SystemRoot" );          // Mono and Shared Source CLI users on Linux, Unix or           // Mac OS X should comment out the preceding two lines          // of code and uncomment the following:          //string theDirectory = "/tmp";          // call the method to explore the directory,          // displaying its access date and all          // subdirectories          DirectoryInfo dir = new DirectoryInfo( theDirectory );          t.ExploreDirectory( dir );          // completed. print the statistics          Console.WriteLine(             "\n\n{0} files in {1}  directories found.\n",             fileCounter, dirCounter );       }       // Set it running with a directoryInfo object       // for each directory it finds, it will call        // itself recursively       private void ExploreDirectory( DirectoryInfo dir )       {          indentLevel++;  // push a directory level          // create indentation for subdirectories          for ( int i = 0; i < indentLevel; i++ )             Console.Write( "  " ); // two spaces per level          // print the directory and the time last accessed          Console.WriteLine( "[{0}] {1} [{2}]\n",             indentLevel, dir.Name, dir.LastAccessTime );          // get all the files in the directory and          // print their name, last access time, and size          FileInfo[] filesInDir = dir.GetFiles( );          foreach ( FileInfo file in filesInDir )          {             // indent once extra to put files             // under their directory             for ( int i = 0; i < indentLevel + 1; i++ )                Console.Write( "  " ); // two spaces per level             Console.WriteLine( "{0} [{1}] Size: {2} bytes",                file.Name,                file.LastWriteTime,                file.Length );             fileCounter++;          }          // get all the directories in the current directory          // and call this method recursively on each          DirectoryInfo[] directories = dir.GetDirectories( );          foreach ( DirectoryInfo newDir in directories )          {             dirCounter++;  // increment the counter             ExploreDirectory( newDir );          }          indentLevel--; // pop a directory level       }    } } Output (excerpt): [0] WINDOWS [9/4/2004 8:37:13 AM]   0.LOG [8/30/2004 8:26:05 PM] Size: 0 bytes   AC3API.INI [1/14/1999 2:04:06 PM] Size: 231 bytes   actsetup.log [7/1/2004 11:13:11 AM] Size: 3848 bytes   Blue Lace 16.bmp [8/29/2002 6:00:00 AM] Size: 1272 bytes   BOOTSTAT.DAT [8/30/2004 8:25:03 PM] Size: 2048 bytes 12630 files in 1444  directories found.

The example is initialized with the name of the SystemRoot directory. It prints information about all the files in that directory and then recursively explores all the subdirectories and all their subdirectories (your output might differ). This can take quite a while to run because the SystemRoot directory tree is rather large (1,444 subdirectories on my machine, as shown in the output).

21.1.4. Modifying Files

As you can see from Tables Table 21-3 and Table 21-4, it's possible to use the FileInfo class to create, copy, rename, and delete files. The next example creates a new subdirectory, copies files in, renames some, deletes others, and then deletes the entire directory.

To set up these examples, create a \test directory and copy the media directory from WinNT or Windows into the \test directory. Don't work on files in the system root directly; when working with system files you want to be extraordinarily careful.


The first step is to create a DirectoryInfo object for the test directory (adjust theDirectory appropriately if you are on a Mac OS X, Linux, or Unix system):

string theDirectory = @"c:\test\media"; DirectoryInfo dir = new DirectoryInfo(theDirectory);

Next, create a subdirectory within the test directory by calling CreateSubDirectory on the DirectoryInfo object. You get back a new DirectoryInfo object, representing the newly created subdirectory:

string newDirectory = "newTest"; DirectoryInfo newSubDir =     dir.CreateSubdirectory(newDirectory);

You can now iterate over the test and copy files to the newly created subdirectory:

FileInfo[] filesInDir = dir.GetFiles(); foreach (FileInfo file in filesInDir) {    string fullName = newSubDir.FullName +         "\\" + file.Name;    file.CopyTo(fullName);    Console.WriteLine("{0} copied to newTest",       file.FullName); }

Notice the syntax of the CopyTo method. This is a method of the FileInfo object. Pass in the full path of the new file, including its full name and extension.

Once you've copied the files, you can get a list of the files in the new subdirectory and work with them directly:

filesInDir = newSubDir.GetFiles( ); foreach (FileInfo file in filesInDir) {

Create a simple integer variable named counter and use it to rename every other file:

if (counter++ %2 == 0) {     file.MoveTo(fullName + ".bak");     Console.WriteLine("{0} renamed to {1}",         fullName,file.FullName); }

You rename a file by "moving" it to the same directory, but with a new name. You can, of course, move a file to a new directory with its original name, or you can move and rename at the same time.

Rename every other file, and delete the ones you don't rename:

file.Delete( ); Console.WriteLine("{0} deleted.",     fullName);

Once you're done manipulating the files, you can clean up by deleting the entire subdirectory:

newSubDir.Delete(true);

The Boolean parameter determines whether this is a recursive delete. If you pass in false, and if this directory has subdirectories with files in it, it throws an exception.

Example 21-3 lists the source code for the complete program. Be careful when running this: when it is done, the subdirectory is gone. To see the renaming and deletions, either put a breakpoint on the last line or remove the last line.

Example 21-3. Creating a subdirectory and manipulating files
#region Using directives using System; using System.Collections.Generic; using System.IO; using System.Text; #endregion namespace CreatingSubdirectoryManipulatingFile {    class Tester    {       public static void Main( )       {          // make an instance and run it          Tester t = new Tester( );          string theDirectory = @"c:\test\media";          DirectoryInfo dir = new DirectoryInfo( theDirectory );          t.ExploreDirectory( dir );       }       // Set it running with a directory name       private void ExploreDirectory( DirectoryInfo dir )       {          // make a new subdirectory          string newDirectory = "newTest";          DirectoryInfo newSubDir =             dir.CreateSubdirectory( newDirectory );          // get all the files in the directory and          // copy them to the new directory          FileInfo[] filesInDir = dir.GetFiles( );          foreach ( FileInfo file in filesInDir )          {             string fullName = newSubDir.FullName +                "\\" + file.Name;             file.CopyTo( fullName );             Console.WriteLine( "{0} copied to newTest",                file.FullName );          }          // get a collection of the files copied in          filesInDir = newSubDir.GetFiles( );          // delete some and rename others          int counter = 0;          foreach ( FileInfo file in filesInDir )          {             string fullName = file.FullName;             if ( counter++ % 2 == 0 )             {                file.MoveTo( fullName + ".bak" );                Console.WriteLine( "{0} renamed to {1}",                   fullName, file.FullName );             }             else             {                file.Delete( );                Console.WriteLine( "{0} deleted.",                   fullName );             }          }          newSubDir.Delete( true ); // delete the subdirectory        }    } } Output (excerpts): c:\test\media\Bach's Brandenburg Concerto No. 3.RMI         copied to newTest c:\test\media\Beethoven's 5th Symphony.RMI copied to newTest c:\test\media\Beethoven's Fur Elise.RMI copied to newTest c:\test\media\canyon.mid copied to newTest c:\test\media\newTest\Bach's Brandenburg Concerto          No. 3.RMI renamed to  c:\test\media\newTest\Bach's Brandenburg Concerto          No. 3.RMI.bak c:\test\media\newTest\Beethoven's 5th Symphony.RMI deleted. c:\test\media\newTest\Beethoven's Fur Elise.RMI renamed to  c:\test\media\newTest\Beethoven's Fur Elise.RMI.bak c:\test\media\newTest\canyon.mid deleted.



Programming C#(c) Building. NET Applications with C#
Programming C#: Building .NET Applications with C#
ISBN: 0596006993
EAN: 2147483647
Year: 2003
Pages: 180
Authors: Jesse Liberty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net