In this article, we will look at the power of the File and FileInfo classes used for file manipulation in C#.  We’ll uncover the similarities and differences between these two classes and why we would want to use one over the other. 

To download the source code for this article, you can visit our GitHub repository.

Let’s begin with some background on the File and FileInfo class.

The File and FileInfo Classes in C#

File and FileInfo are classes in C# that provide methods for manipulating files. They provide the functionalities we need to programmatically create, read, update, and delete files. Both classes are located in the System.IO namespace and have similar functionalities. However, there are some key differences between them that we should take note of.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

The File class is a static class, which means that all of its methods are called directly on the class itself, rather than on an instance of the class. It exposes static methods which we can use to create, delete, move, or even append text to a file.

FileInfo, on the other hand, is a non-static class, so we must create an instance of the class in order to use its methods.

The File class has a lot of methods similar to those found in the FileInfo class. We can use these methods interchangeably.

How to Create a File in C#

We can use the File.Create()  and FileInfo.Create() methods to create a file:

//Create a file Using the File class
using FileStream fileCreatedUsingFileClass = File.Create("myFileOne.txt");
           
//Create a file using the FileInfo class
FileInfo fileInfo = new("myFileTwo.txt");
FileStream fileCreatedUsingFileInfoClass = fileInfo.Create();

The difference between these approaches is that File.Create() is a static method while FileInfo.Create() is an instance method. Also, we are required to pass in a path parameter when dealing with the File.Create() method.

In terms of similarity, notice how File.Create() and Fileinfo.Create() both return a strongly typed FileStream class. We can take it one step further by using synchronous and asynchronous methods in FileStream to read and write files.

Let’s look at some other methods of the File and FileInfo classes that return a FileStream object.

How to Open a File in C#

The File.Open() and FileInfo.Open() methods allow us to open a file. The Open method has different overloads that allow us to specify the FileMode, FileAccess and FileStreamOptions. 

FileMode is an enum that allows us to specify if we want to overwrite a file or create a new file if the specified one doesn’t exist:

//Open a file in Create mode using File classs
using FileStream fileOne = File.Open("myFileThree.txt", FileMode.Create);

//Open a file in Create mode using FileInfo
FileInfo fileInfo = new("myFileTwelve.txt");            
using FileStream result = fileInfo.Open(FileMode.Create);     

As the name signifies, FileAccess is an enum that allows us to specify read and write access to a file:

//Open a file with FileMode.Create, FileAccess.Write using File 
using FileStream fileAccess = File.Open("myFileThree.txt", FileMode.Create, FileAccess.Write);
fileAccess.Close();
File.Delete("myFileThree.txt");

//Open a file with FileMode.Create, FileAccess.Write using FileInfo
FileInfo fileInfo = new("myFileTwelve.txt");
using FileStream fileInfoAccess = fileInfo.Open(FileMode.Create, FileAccess.Write);
fileInfoAccess.Close();
fileInfoAccess.Dispose();
fileInfo.Delete();

We can use FileShare to specify the level of access other operations can have for a file that is in use:

//Open a file with FileMode.Create, FileAccess.Write, FileShare.ReadWrite using File 
using FileStream share = File.Open("myFileZ.txt", FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
share.Close();
share.Dispose();

//Open a file with FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite using FileInfo 
FileInfo fileInfo = new("myFileTwelve.txt");
using FileStream infoShare = fileInfo.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
infoShare.Close();
infoShare.Dispose();

The last overload of the Open method takes in a FileStreamOptions:

var fileStreamOptions = new FileStreamOptions()
{
    Access = FileAccess.Read, 
    Share = FileShare.ReadWrite, 
    Mode = FileMode.OpenOrCreate 
};

//Open a file with FileStreamOptions using File
using FileStream fileStream = File.Open("myFileTwentyTwo.txt", fileStreamOptions);
fileStream.Dispose();
File.Delete("myFileTwentyTwo.txt");

//Open a file with FileStreamOptions using FileInfo
FileInfo fileInfo = new("myFileTwelve.txt");
using FileStream fileInfoFileStream = fileInfo.Open(fileStreamOptions);
fileInfoFileStream.Close();
fileInfoFileStream.Dispose();

The FileStreamOptions class allows us to specify several details used in manipulating a file – the file mode, file access, file share options, etc. We create an instance of the FileStreamOption class and used it in opening the file using File and FileInfo.

How to Open a Read-only File in C#

Next, let’s look at how to open a read-only file. In this case, we will use File.OpenRead()/ FileInfo.OpenRead() method:

if (!File.Exists("sampleReadOnlyFileTwo.txt"))
{
    var fs = File.Create("sampleReadOnlyFileTwo.txt");
    fs.Close();
}

//Open a read-only file stream with static File.OpenRead()
using FileStream openReadFileResult = File.OpenRead("sampleReadOnlyFileTwo.txt");
openReadFileResult.Dispose();
File.Delete("sampleReadOnlyFileTwo.txt");

//Open a read-only file stream with instance FileInfo.OpenRead()
FileInfo fileInfo = new("myFileTwo.txt");
if (!fileInfo.Exists) 
    fileInfo.Create();

using FileStream openReadFileInfoResult = fileInfo.OpenRead();
openReadFileInfoResult.Dispose();
fileInfo.Delete();

We first create the file if it does not already exist because OpenRead requires that the specified file exists. If we call OpenRead on a non-existent file, an exception will be thrown.

How to Use OpenWrite Method in C#

Let’s check out how to open an existing file or create a new file for writing by using the OpenWrite() method:

//Open or create a file stream with static File.OpenWrite()
using FileStream openWriteFileResult = File.OpenWrite("myFileFive.txt");            

//Open or create a file stream with instance FileInfo.OpenWrite()
FileInfo fileInfo = new("myFileFourteen.txt");
using FileStream openWriteFileInfoResult = fileInfo.OpenWrite();

The OpenWrite method always overwrites the content of a file and will create a new file for us if the file path we specified does not exist.

How to Use File With StreamReader and StreamWriter in C#

We looked at different ways in which we could create or open a file. Next, let’s check out how we can use File with StreamWriter and StreamReader classes to create and read from a file.

Create a File Using CreateText

if (!File.Exists("sampleDocument.txt")) 
{
    //To create a file 
    using (StreamWriter streamWriter = File.CreateText("sampleDocument.txt"))
}

We use the CreateText method to open and overwrite the contents of a file using  StreamWriter. If the file doesn’t exist, it will create a new file for writing UTF-8 encoded text. CreateText returns a StreamWriter which we can use to write to the created file.

Write to a File Using StreamWriter

We will use StreamWriter.WriteLine to write to sampleDocument.txt:

if (!File.Exists("sampleDocument.txt"))
{
    //To create a file
    using StreamWriter streamWriter = File.CreateText("sampleDocument.txt");
    
    //To write to the file
    streamWriter.WriteLine("My Todo");
    streamWriter.WriteLine("Drink Water");
    streamWriter.WriteLine("Be Awesome");
}

streamWriter.WriteLine will write a string to the current stream and then add a line terminator so that the next text starts on a new line.

Read From a File Using StreamReader

We are using the StreamReader instance to read text from a file:

using StreamReader streamReader = File.OpenText("sampleDocument.txt");
string result;

StringBuilder sr = new();
while ((result = streamReader.ReadLine()) != null)
{
    sr.Append(result);
}

sr.ToString();

ReadLine is used to read the content of our file line and then we store the result in a StringBuilder. We can simply write the result of this operation to the console by calling ToString on the StringBuilder:
Console.WriteLine(sr.ToString());

Let’s see how we would achieve the same result using FileInfo.

How to Use FileInfo Class With StreamReader and StreamWriter in C#

Let’s look at how we can create a file, write to it and then read its content using FileInfo:

FileInfo fileInfo = new("SampleDocument.txt");

if (!fileInfo.Exists)
{
    //To create a file
    using StreamWriter streamWriter = fileInfo.CreateText();
    
    //To write to the file
    streamWriter.WriteLine("My Todo");
    streamWriter.WriteLine("Drink Water");
    streamWriter.WriteLine("Be Awesome");
}

//To open and read from the created .txt file
using StreamReader streamReader = fileInfo.OpenText();
string result;

StringBuilder sr = new();
while ((result = streamReader.ReadLine()) != null)
{
    sr.Append(result);
}

The difference here is that, unlike the File example where we use those static classes, we use a single instance of FileInfo to create, write and read from a file.

When to Use File Over FileInfo and Vice Versa in C#

The decision of whether to use File or FileInfo depends on the specific task at hand. Let’s look at key features that could influence our decision.

The Security Checks of the File Class Static Methods in C#

It is important to note that the File class can only work on a single file at a time and that’s why we always have to specify a file path for every method call. Also, each static method of the File class has a built-in security check designed to secure the specified file.

To put this in perspective, let’s look at our previous example where we used the File class with a StreamWriter and StreamReader to create, write and read from a file. In that example, we made three calls – File.Exist(path), File.CreateText(path), and File.OpenText(path) – this resulted in three security checks being performed, whether necessary or not.

On the other hand, the FileInfo class uses a single instance and performs security checks only when necessary. 

The Caching System of the FileInfo Class In C#

The FileInfo class has a caching system, which stores the properties of a file the first time it is retrieved. This allows for faster access to file information, but it’s important to call the Refresh method to ensure the cached information is up-to-date. If the Refresh method is not called, we will get the outdated version of the file information:

fileInfo.Attributes = FileAttributes.Hidden;
fileInfo.Refresh();
Console.WriteLine(fileInfo.Attributes.ToString());

Final Thoughts about File and FileInfo

The File class, being a static class, is a better choice when we want to perform just a single operation on one or multiple files:

File.Copy("myFileSix.txt", "myFileSeven.txt");
File.Encrypt("myFileSix.txt");
File.Decrypt("myFileSix.txt"); 
File.Move("myFileSeven.txt", "myFileSix.txt");
File.Delete("myFileSix.txt");
File.Delete("myFileSeven.txt");

However, if we need to perform multiple operations on a single file and require additional functionality, then the FileInfo class would be more suitable. It circumvents the multiple security checks of the static methods of File class and preserves OOP:

FileInfo fileInfo = new("myFileSixteen.txt"); 
fileInfo.OpenText(); 
fileInfo.Encrypt(); 
fileInfo.Decrypt();
fileInfo.Delete();

Conclusion:

In this article, we have compared the File and FileInfo classes in C#. The File and FileInfo classes provide a powerful and flexible set of methods for file manipulation in C#. We have also looked at suggestions for when to use one over the other for better performance.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!