This chapter deals with the filesystem in four distinct ways. The first set of recipes looks at typical file interactions like creation, reading and writing, deletion, attributes, encoding methods for character data, and how to select the correct way (based on usage) to access files via streams. The second set looks at directory- or folder-based programming tasks like file creation as well as renaming, deleting, and determining attributes. The third set deals with the parsing of paths and the use of temporary files and paths, and the fourth set deals with more advanced topics in filesystem I/O, like asynchronous reads and writes, monitoring for certain filesystem actions, version information in files, and using P/Invoke to perform file I/O.
The file interactions section comes first since it sets the stage for many of the recipes in the temporary file and advanced sections. This is foundational knowledge that will help you understand the other file I/O recipes and how to modify them for your purposes. The various file and directory I/O techniques are used throughout the more advanced examples to help show a couple of different ways to approach the problems you will encounter working with filesystem I/O.
Unless otherwise specified, you need the following
using
statements in any program that uses snippets
or methods from this chapter:
using System; using System.IO;
You need to create a new file, copy an existing file, move an existing file, or delete a file.
The System.IO
namespace contains two classes to
perform these actions: the File
and
FileInfo
classes. The
File
class contains
only static methods, while the
FileInfo
class contains
only instance methods.
File
’s static
Create
method returns an instance of the
FileStream
class, which you can use to read from or write to the newly created
file. For example, the following code uses the static
Create
method of the File
class
to create a new file:
FileStream fileStream = null; if (!File.Exists(@"c:delete est est.txt")) { fileStream = File.Create(@"c:delete est est.txt"); }
The
Create
instance method of the
FileInfo
class takes no parameters. You should
supply the path with a filename as the only parameter to the
FileInfo
class constructor. The method returns an
instance of the FileStream
class that you can use
to read from or write to the newly created file. For example, the
following code uses the Create
instance method of
the FileInfo
class to create a new file:
FileInfo fileInfo = null; FileStream fileStream = null; if (!File.Exists (@"c:delete est est.txt")) { fileInfo = new FileInfo(@"c:delete est est.txt"); fileStream = fileInfo.Create( ); }
You can
copy a file using the overloaded static File.Copy
method that returns void
. The third parameter of
one of the overrides for this function allows you to pass
true
or false
depending upon
whether you want to overwrite an existing destination file, as shown
in the following code, which uses the static Copy
method of the File
class to copy a file:
if (File.Exists(@"c:delete est est.txt")) { File.Copy(@"c:delete est est.txt ", Directory.GetCurrentDirectory( ) + @" est.txt", true); }
The
overloaded CopyTo
instance method returns a
FileInfo
object that represents the newly copied
file. This method can also take a Boolean in one of the overrides to
signify your intent to overwrite an existing file. For example, the
following code uses the CopyTo
instance method of
the FileInfo
class to copy a file:
FileInfo fileInfo = new FileInfo(@"c:delete est est.txt"); fileInfo.CopyTo(@"c: est.txt", true);
You can
move a file using the static Move
method of the
File
class, which returns void
.
For example, the following code uses the static
Move
method to move a file after checking for its
existence:
if (!File.Exists(Directory.GetCurrentDirectory( ) + @" est.txt")) { File.Move(@"c:delete est est.txt ", Directory.GetCurrentDirectory( ) + @" est.txt"); }
The
MoveTo
instance method returns
void
and is the way to move a file using the
FileInfo
class. For example, the following code
moves a file using the MoveTo
instance method of
the FileInfo
class after checking for the
file’s existence:
FileInfo fileInfo = new FileInfo(@"c:delete est est.txt"); if (!File.Exists(@"c: est.txt ")) { fileInfo.MoveTo(@"c: est.txt "); }
You
can delete a file using the static Delete
method
of the File
class that returns
void
. For example, the following code uses the
static Delete
method to delete a file:
if (File.Exists(Directory.GetCurrentDirectory( ) + @" est.txt")) { File.Delete(Directory.GetCurrentDirectory( ) + @" est.txt", true); }
The
Delete
instance method on the
FileInfo
class takes no parameters and returns
void
. For example, the following code uses the
Delete
instance method of the
FileInfo
class to delete a file:
if(File.Exists(@"c:delete est est.txt") { FileInfo fileInfo = new FileInfo(@"c:delete est est.txt"); fileInfo.Delete( ); }
Whether you choose to call the
static file operation methods or the instance file operation methods
depends on what you are trying to accomplish. If you need a quick way
of creating, moving, copying, or deleting a file, consider using the
static methods. If you will be performing multiple operations on a
file, such as creating, moving, and changing its attributes, you
should consider the instance methods of the
FileInfo
class. Another consideration is that
static methods on a class do not require an object to be created on
the managed heap and subsequently destroyed by the garbage collector.
Instance methods require an object to be created before the methods
can be called. If you are trying to minimize the number of objects
the garbage collector has to manage, consider using static methods.
A few items to note when using the file functions:
If the directory doesn’t exist, the method won’t create it and you’ll get an exception. See how to check whether a directory exists in Recipe 11.4.
If no path is provided, the file
will land in the current working directory. If the user does not have
permission to write to the current working directory (such as the
case of a normal user writing to the Program
Files
directory), this will result in an
UnauthorizedAccessException
.
If a relative path is provided (for example,
C:dir1dir2....file.txt
), it will be
evaluated properly.
If an absolute path is provided, the method will succeed as expected.
When
creating a new file, you should first determine whether that file
already exists. This is a good idea since the default creation
behavior of the file classes is to either overwrite the existing file
silently or, if the file is read-only, to throw an exception. The
File
and FileInfo
classes both
contain a method,
Exists
, to perform
this operation. Once it is determined that the file does not exist,
we can create it using either the static or instance
Create
methods. Note that this does leave a small
window open between the time you checked and the time that the
creation starts, so it is not a replacement for proper exception and
error handling of the Create
call.