Often when programming, you’ll find that you need to read or write to a standard text file. In this tutorial I’ll show you the basics on text file access, as well as a few more tricks to help smooth things along.

The first thing you’ll need to know is that most of the things you will need are located in System.IO. In this class you’ll find many things that are usefull, a brief list is included below. I’ll touch on some of these, but I won’t go over all of them, as you’ll notice there are a good number of them.

BinaryReader, BinaryWriter, BufferedStream, Directory, DirectoryInfo, DriveInfo, DriveType, File, FileInfo, FileStream, FileSystemInfo, MemoryStream, Path,
Stream, StreamReader, StreamWriter, TextReader, TextWriter

To use this class add this line to the top of your source file:

using System.IO;

If you have MS Visual Studio, go to View – Object Browser, and search System.IO for the full list of all methods and members of that class.
Now, looking at the list above, you’ll notice that there are several different readers/writers available. You’d probably guess that TextReader/TextWriter would be the classes that we will be working with for text files, but you’d be wrong in that guess.

I don’t use the Text(Reader/Writer) classes because to instantiate them you have to use the Stream(Reader/Writer) classes. Plus, the Stream classes offer more options than the Text classes.

But for completion, you would instantiate the Text objects as:

TextReader tReader = newStreamReader(FileName);
TextWriter tWriter = newStreamWriter(FileName);

Conversely, to instantiate Stream objects you do essentially the same thing:

StreamReader sReader = newStreamReader(FileName);
StreamWriter sWriter = newStreamWrtier(FileName);

For the rest of this tutorial we’re going to assume that we are using the stream objects above. (Not the text objects.)

This instantiation does two things at once, first it opens the file, then it provides a reference to the open file via the variable (sReader/sWriter).

So, lets work on reading the file first, then when we’re done with that we’ll move on to writing to the file.

Since we have a reference to the open file for reading (sReader), we now need to know how to read the contents of the file. For this, we have three options; ReadLine, ReadToEnd, and ReadBlock. I personally don’t use ReadBlock, so I won’t be covering that here.

ReadLine does exactly what it sounds like it’s supposed to do. It reads the file, one line at a time and returns the line as a string. Simple enough, right? But how do you know when to stop reading?

StreamReader provides an awesome little Boolean that tells us whether or not we are at the end of the file. To be safe, we should check to make sure we aren’t at the end of the file before each and every we read from it. Sounds tedious, doesn’t it?

using(StreamReader sReader = newStreamReader(Filename))
{
while(!sReader.EndOfStream)
{
string line = sReader.ReadLine();
Console.WriteLine(line);
}
}

A lot simpler than it sounds, right? The above piece of code will read the entire file, one line at a time, and output it to the console screen.

Now what’s with that using statement, I thought those only went at the top of the source page? Nope, the using statement, in this case provides an element of error protection. If for some reason the StreamReader can’t access the file, like if it doesn’t exist, then the using statement will terminate without throwing any errors. It also protects us from infinitely open files, as we humans sometimes forget to close them.

What if we want to receive the error messages? Simple, modify the above code to look like this:

StreamReader sReader = newStreamReader(Filename);
while(!sReader.EndOfStream)
{
string line = sReader.ReadLine();
Console.WriteLine(line);
}
sReader.Close();

Notice this time that we have to manually close the file? That’s because in the above using statement, the system automatically closes the file when the code processing exits the using statement.

Now, onto ReadToEnd method. Just like the ReadLine method it returns a string, the difference is this time the string contains the entire contents of the file. Another major difference is you don’t have to check for the end of the file, because we already know we’ll reach it on the first read. If the file is empty, then it’ll return an empty string. Nifty eh?

StreamReader sReader = newStreamReader(Filename);
string fileContents = sReader.ReadToEnd();
Console.WriteLine(fileContents);

Once again, we’ve read the entire file and printed it to the console screen, but with fewer lines of code. If we can read an entire file at once, why would we want to read a line at a time? There are times when you will want to read just one line at a time, then process that line before reading the next line. While it’s still possible to do this by reading the entire file at once, it’s a little bit trickier. Conversely, if you are writing an application such as Notepad, you’d have no reason to process each line, so reading the entire file at once would be faster.

That covers reading from file, now let’s get onto writing to it. The StreamReader object offers two methods for writing to a file; Write and WriteLine.

Assuming you have a string named OutString that contains data to be written to a text file, the following two chunks of code both do the same thing:

StreamWriter sWriter = newStreamWriter(Filename);
sWriter.WriteLine(OutString);
StreamWriter sWriter = newStreamWriter(Filename);
sWriter.Write(OutString);
sWriter.Write(sWriter.NewLine);

Whoah, what was that last line? WriteLine writes the contents of the string to the file then terminates the end of the line. Write does not terminate the end of the line. If you string contained 10 lines, then WriteLine would write 10 lines then stop at the beginning of the 11th line. Write on the otherhand would stop at the end of the 10th line.

Aside from that, you can enlist a using statement, or a close statement just as you would for a StreamReader.

Now, let me cover some additional tricks. Before you open a file for reading, you should check to make sure the file exists. Attempting to open a nonexistant file will cause an error, and if you don’t use error handling, will crash your application. To check to make sure the file exists, use the File object located in the System.IO class:

if(File.Exists(Filename))
{
// Process your file here
}

If the file doesn’t exist, then File.Exists returns false, exiting the above statement.

Now here’s a few other usefull things located in the System.IO class:

Open a file, append some text, and close the file all in one move

void AppendAllText(string path, string contents)

Copy a file to another, and specify if you want to overwrite the target file

void Copy(string sourceFileName, string destFileName, bool overwrite)

Create a file with no contents and return a FileStream object to it

FileStream Create(string path)

Encrypt/decrypt a file

Files encrypted using these can only be decrypted by the same user account on the same pc on which it was encrypted. In other words, only good for your personal files, don’t use for files you’re sending to someone else.

void Encrypt(string path)
void Decrypt(string path)

Get the date and time a file was created, accessed, or written to

DateTime GetCreationTime(string path)
DateTime GetLastAccessTime(string path)
DateTimeGetLastWriteTime(string path)

Set the date and time a file was created, accessed, or written to

void SetCreationTime(string path, DateTime creationTime)
void SetLastAccessTime(string path, DateTime lastAccessTime)
void SetLastWriteTime(string path,DateTime lastWriteTime)