Data Persistence – Reading From and Writing to Text Files

Updated: Jan 13

Most applications you write will need to store information to be retrieved at a later time. No application user wants to enter the same information over and over again. Forcing them to do so is a sure-fire way to have them looking for software to replace yours.

There are many ways you can store information from your application. This post will show you one of the simplest to understand and implement. This post will cover reading data from a text file as well as storing data to one.


SYSTEM.IO

If you want to work with files and data streams, you will need the types and methods stored in the System.IO namespace. To access those elements, implement the using statement for that namespace.

using System.IO;

The IO stands for Input/Output, and this namespace provides you with ways to read data from and write data to files as well as manipulate files with your directories.


File Class

File is a static class found in the System.IO namespace that provides methods for manipulating a file. File methods exist for creating, opening, reading, moving, and deleting a single fine.


For the File method examples in the post, I will be using a text file named “Data.txt” that I will store in my D:\Stuff directory.


The file has five items, each on a separate line

· Shoes

· Hats

· Socks

· Shirts

· Pants


Now I’m going to write some code that will read that text file in two separate ways. The first way will read all of the information as one block of text. The second way will iterate through the file, line by line, and add each line in a string collection.


Exists

Before I do any work with a file, I should always make sure it exists. If I try to access a file that does not exist, the application will throw a FileNotFound exception. I could use a TRY…CATCH to handle that exception if the file isn’t there. However, System.IO provides me with an Exists() method that will check for the existence of the file and return a Boolean value.


The following code sample checks for the existence of a file and uses an IF statement to respond.

 string path = @"D:\Stuff\Data.txt";
 
 if (File.Exists(path)== false)
 {
      Console.WriteLine("The file is missing."); 
 }
 else
 {
      Console.WriteLine("File Found.");
 }

Once I know that the file I want to work with exists, I can read it.


ReadAllText

The ReadAllText() method will store all of the text from the file into a single string variable. The method handles the opening and closing of the file, so you won’t have to worry about it.

 string allText = File.ReadAllText(path);
 Console.WriteLine(allText);

This code will read the items from my text file and display them in the console window just as they appear in the text file.


Sometimes I don’t want to grab all the text into a single variable. Sometimes I need to work with each line individually.


ReadAllLines

With ReadAllLine(), my application will read each line of the file and populate an element of string collection. By doing this, I can work with each line individually. If you don’t do any explicit conversions, the default collection is a String array.

 string[] allLines = File.ReadAllLines(path);
 
 foreach (string line in allLines)
 {
      Console.WriteLine($"In my closet, I have {line}");
 }

AppendAllLines

The AppendAllLines() method allows you to populate a list then use that list to append lines to a file.

 string[] newItems = new string[] { "Boots", "Jackets", "Gloves" };
 File.AppendAllLines(path, newItems);

WriteAllLines

If you populated the entire collection with your code and wanted to write it to the new file, you can use the WriteAllLines() method. This method will create the file for you then iterate through your collection, writing each line to the new file.

 string[] kids = new string[] { "Jacoby", "Timmy", "Jack", "Cameron" };
 File.WriteAllLines(@"D:\Stuff\BirtdayGuests.txt",kids);

This code will create a new file named “BirthdayGuests.txt” and populate it with the strings from the collection.

Manipulating Files

In addition to creating, reading, and writing to files, the File class also provides methods for manipulating files.


Create – Creates the file with the path provided to the method

Copy – Copies the information from an existing file into a new file created by the method.

Move – Moves the file from one location to the provided new location.

Delete – Deletes the file


File Streams

When you want to read information from or write data to a file, Visual Studio creates a “file stream.” In nature, a stream will carry water from one body of water to another. When working with a file, the stream carries data from one entity to another. Streams allow efficient reading of large files and writing large amounts of data to a file by breaking down data into small chunks and “stream” the information.


The System.IO namespace provides many classes and methods that you can use to read or write to that stream. The two classes we will using within this section are StreamReader and StreamWriter.


StreamReader

The StreamReader object creates an input stream that allows you to retrieve information from a file. The information from the file is added to the stream. The stream is then used within your application. The key to remember is that once your application reads a character from the stream, it’s pointer moves past that character onto the next character in the string. It’s similar to a Stack collection; once the character is read, it is taken out of the stream.


A StreamReader object is created like any object in C# by assigning a value then using the NEW keyword to initialize the object. There are several constructor overloads for creating a new streamreader. For simplicity’s sake, we are going to use the most common way to create a streamreader. We will pass the path of a file to the constructor.

 string path = @"D:\Stuff\Data.txt";
 StreamReader reader = new StreamReader(path);

We now have a stream with all of the information from Data.txt. It’s time to do something with it.


StreamReader Methods

Read – This method will read the next character in the stream.

Peek – This method will peek into the stream to see if there are any more characters in the stream.


Read and Peek are often used together to ensure the Read method does not throw an exception by reading an empty string.

 while (reader.Peek() >= 0)
 {
      Console.WriteLine((char) reader.Read());
 }

ReadToEnd – This method is at the opposite end of the spectrum than the Read method. ReadToEnd reads all of the characters from the current point in the stream to the end of the stream.

 Console.WriteLine(reader.ReadToEnd());

This line of code will display in the console window the text as it appears in the text file.


ReadLine – Although Read and ReadToEnd are used from time to time, the most common method when working with a streamreader is ReadLine. This method allows you to read the stream, line by line, providing you with the functionality to treat the information in a file as a collection.


Every time you call the ReadLine method, you are removing a line of characters from the stream. When you have read all the lines, ReadLine will return a NULL value. Checking for NULL is the way you can safely loop through the lines without throwing and exception.

 string textLine = reader.ReadLine();
 while (textLine != null)
 {
      Console.WriteLine(textLine);
      textLine = reader.ReadLine();
 }

USING Keyword

When working with files, it is crucial to understand that when you create a stream, you are opening that file in memory. If you don’t close that file when you are done with it, an error can occur later in your application if you need to use that file again. To aid you in ensuring the file is closed when you are finished with it, C# provides you with the USING keyword.

The USING keyword allows you to wrap a resource within a code block. When that code block exits, that application will dispose of any connections to that object and clean up any memory that it was utilizing.


The following example creates a USING block around our text file. When the closing bracket is hit, the text file is closed, and the memory is cleared.


 string path = @"D:\Stuff\Data.txt";
 using (StreamReader reader = new StreamReader(path))
 {
      string textLine = reader.ReadLine();
      while (textLine != null)
      {
           Console.WriteLine(textLine);
           textLine = reader.ReadLine();
      }
 } // the file is closed here

The USING keyword can be used with any object that you chose. If the object must be disposed of when the code block is complete, wrap a USING around it.


If you don’t utilize the USING keyword, you must use the Close() method when you are done working with a StreamReader or StreamWriter.

StreamWriter

You have learned how to read from a file. Now it’s time to understand how to write to a file. The most efficient way to do this is with a stream object for the same reasons that were mentioned earlier. To do this, you will create a StreamWriter object.

 string path = @"D:\Stuff\Data.txt";
 StreamWriter writer = new StreamWriter(path);

What's nice about the StreamWriter constructor is that if the file doesn’t exist, it will create the file for you. If the file does exist, you can pass in a Boolean value specifying if you want the streamwriter to append to the existing file (true) or overwrite it (false). Make sure you utilize the USING keyword as well to protect your application from file exceptions.

 string path = @"D:\Stuff\Data.txt";
 using (StreamWriter writer = new StreamWriter(path, true))
 {
 
 }

Once you have your streamwriter object, you can use its methods to start writing to the file.


StreamWriter Methods

The methods to write to a stream are the same as writing to the Console window.


Write() – this method will write the provided text to the file. It will not advance to the next line after the write is complete.

WriteLine() – this method will write the provided text to the file then advance to the next line.

 string path = @"D:\Stuff\Data.txt";
 using (StreamWriter writer = new StreamWriter(path, true))
 {
 writer.Write("A");
 writer.Write("B");
 writer.WriteLine("C");
 writer.WriteLine("D");
 writer.Write("E"); 
 }

This code will write the following lines to the file

ABC

D

E


Storing information from a collection to a file is as easy as adding a FOREACH loop to your code.


 string path = @"D:\Stuff\Data.txt";
 List<string> pets = new List<string>() 
 { "Bear", "Pippa", "Tron", "Ichabob", "Benson" };
 using (StreamWriter writer = new StreamWriter(path, true))
 {
      foreach (string pet in pets)
      {
           writer.WriteLine($"{pet} is a very good pet.");
      } 
 }

82 views0 comments

Recent Posts

See All