Files play an extremely important role on a computer. They hold text, pictures, Microsoft Word documents, spreadsheets, and all sorts of other data. They also hold executable programs, including those that provide the operating system itself.
In this lesson you learn some basic techniques for reading and writing text files. Using some fairly simple techniques, you can use text files to store and retrieve data used by a program.
There are many kinds of files: web pages, video, audio, executable, and many others. At some level, however, files are all the same. They're just a series of bytes stored on a file system somewhere.
Thinking about files at this very low level enables you to treat them uniformly. That is, you can define common classes and methods that you can then use to manipulate any kind of file.
Many programming languages, including Visual Basic, make working with files at a low level easier by defining the concept of a stream. A stream is simply an ordered series of bytes.
Streams can also represent things other than files. For example, a stream could represent data being sent from one program to another, a series of bytes being downloaded from a web site, or the flow of data as it moves through some complex process such as encryption or compression. This lesson focuses on file streams.
Stream objects provide methods for manipulating streams at a low level. For example, the Stream
class provides Read
and Write
methods that move bytes of data between the stream and an array of bytes in your program.
Working with streams at this low level is convenient for some programs, but it makes day-to-day file handling difficult. You probably don't want to read the bytes from a text file and then reassemble them into characters.
The StreamReader
and StreamWriter
classes make reading and writing text streams much easier. As you can probably guess from their names, StreamReader
enables a program to read text from a stream, and StreamWriter
enables a program to write text into a stream. If that stream happens to represent a file, then you're reading and writing files.
The .NET Framework uses namespaces to categorize the classes it provides so they are easier to find and organize. The StreamReader
and StreamWriter
classes are in the System.IO
namespace, so you can refer to them as System.IO.StreamReader
and System.IO.StreamWriter
.
However, to make it easier to use these classes, you can add the following Imports
directive at the very beginning of a code file:
Imports System.IO
After adding that directive, you can refer to these classes without the System.IO
prefix.
The StreamWriter
class provides several constructors to build a StreamWriter
associated with different kinds of streams. One of the simplest constructors takes a filename as a parameter. It opens the file for writing and associates the new StreamWriter
with it.
Before you create a StreamReader
or StreamWriter
, however, you should know a bit about the Dispose
method and the Using
statement (see the accompanying "Using Using" sidebar).
The following code shows how a program can open the file Memo.txt
for writing. If the file already exists, it is overwritten.
' Write into the file, overwriting it if it exists. Using memoWriter As New StreamWriter("Memo.txt") ' Write into the file. '... End Using
If you pass the constructor a filename without a path, such as Memo.txt
, the program creates the file in its current directory. You can use a fully qualified filename such as C:TempMemo.txt
to create the file in a particular directory.
Another version of the class's constructor takes a second Boolean
parameter that indicates whether you want to open the file for appending. If you set this parameter to True
, the StreamWriter
opens the existing file and prepares to add text to the end. If the file doesn't exit, the object silently creates a new file and gets ready to append.
The StreamWriter
class provides a Write
method to add text to the file. The WriteLine
method adds text followed by a new line. Both Write
and WriteLine
have a bunch of overloaded versions that write various data types into the file: Boolean, Char, String, Integer, Decimal
, and so on. They also provide versions that take a format string and parameters, much as the String.Format
method does.
The StreamWriter
provides one other very important method that I want to cover here: Close
. The Close
method closes the StreamWriter
and its associated file. When you use the Write
and WriteLine
methods, the StreamWriter
may actually buffer its output in memory and only write to the file when it has saved up enough data to make writing to the disk efficient. The Close
method forces the StreamWriter
to flush its buffer into the file. Until that point, the data may not actually be in the file. If your program crashes or ends without calling Close
, there's a very good chance that some or all of your text may be lost.
The following code shows how a program could save the contents of a textbox in a file:
' Write the file, overwriting it if it exists. Using memoWriter As New StreamWriter("Memo.txt") ' Write the file. memoWriter.Write(txtMemo.Text) memoWriter.Close() End Using
The StreamReader
class enables you to easily read text from a file. Like the StreamWriter
class, StreamReader
provides a constructor that takes a parameter specifying the name of the file to open. It also implements IDisposable
, so you should call a StreamReader
's Dispose
method or use it in a Using
statement.
Note that the constructor throws an exception if the file doesn't exist, so your program should verify that the file is there before you try to open it. One way to do that is to use the File
class's static Exists
method. For example, the code File.Exists("Memo.txt")
returns True
if the file Memo.txt
exists in the program's current directory.
The StreamReader
class provides a Read
method that enables reading from the file one or more bytes at a time, but usually you'll want to use its ReadLine
and ReadToEnd
methods.
As you may be able to guess, ReadLine
reads the next line from the file and returns it as a string. ReadToEnd
reads the rest of the file from the current position onward and returns it as a string.
The following code reads the file Memo.txt
and displays its contents in a textbox:
' Read the file. Using memoReader As New StreamReader("Memo.txt") txtMemo.Text = memoReader.ReadToEnd() memoReader.Close() End Using
The StreamReader
's EndOfStream
property returns True
if the reader is at the end of the stream. This is particularly useful when reading a stream of unknown length. For example, the program can enter a While
loop that uses ReadLine
to read lines and continue as long as EndOfStream
is false.
In this Try It, you build the program shown in Figure 31-1. When the program starts, it loads previously saved values into its textboxes. When it stops, the program saves the values that are currently in the textboxes.
You can download the code and resources for this Try It from the book's web page at www.wrox.com
or www.vb-helper.com/24hourvb.html
. You can find them in the Lesson31 folder of the download.
In this lesson:
Start a new project and arrange its form as shown in Figure 31-1.
Give the form a Load
event handler that uses a StreamReader
to open the file Values.txt
and read the file's lines into the form's textboxes.
Give the form a FormClosing
event handler that uses a StreamWriter
to open the file Values.txt
and write the values in the textboxes into the file.
Use an Imports System.IO
directive.
Use the StreamReader
and StreamWriter
inside Using
blocks.
Make sure the file exists before you try to open it.
Use a module-scope constant to hold the file's name so all of the code can share it.
Start a new project and arrange its form as shown in Figure 31-1.
This is reasonably straightforward.
Give the form a Load
event handler that uses a StreamReader
to open the file Values.txt
and read the file's lines into the form's textboxes.
Use code similar to the following:
' The file's name. Private Const FileName As String = "Values.txt" ' Load the saved values. Private Sub Form1_Load() Handles MyBase.Load ' See if the file exists. If File.Exists(FileName) Then ' Open the file. Using valueReader As New StreamReader(FileName) txtFirstName.Text = valueReader.ReadLine() txtLastName.Text = valueReader.ReadLine() txtStreet.Text = valueReader.ReadLine() txtCity.Text = valueReader.ReadLine() txtState.Text = valueReader.ReadLine() txtZip.Text = valueReader.ReadLine() valueReader.Close() End Using End If End Sub
Give the form a FormClosing
event handler that uses a StreamWriter
to open the file Values.txt
and write the values in the textboxes into the file.
Use code similar to the following:
' Save the current values. Private Sub Form1_FormClosing() Handles Me.FormClosing ' Create the file. Using As New StreamWriter(FileName) valueWriter.WriteLine(txtFirstName.Text) valueWriter.WriteLine(txtLastName.Text) valueWriter.WriteLine(txtStreet.Text) valueWriter.WriteLine(txtCity.Text) valueWriter.WriteLine(txtState.Text) valueWriter.WriteLine(txtZip.Text) valueWriter.Close() End Using End Sub
Please select Lesson 31 on the DVD to view the video that accompanies this lesson.
Build a Memo program that saves and loads a single memo saved in the file in a multiline textbox. Hint: Should you use Write
or WriteLine
? (This is so easy I wouldn't normally use it as an exercise but it's actually useful. You can use it to record notes during the day and easily review them the next day.)
Make a program that lets the user select a number N from a NumericUpDown
control and then generates a file containing a multiplication table showing the products 1 × 1 through N × N. Use formatting to make the numbers line up in columns.
Build a program with a TextBox
, a ListBox
, an Add button, and a Save button. When the user enters a value in the TextBox
and clicks Add, add the value to the ListBox
. When the user clicks Save, write the values from the ListBox
into a file and then clear the ListBox
. When the form loads, make it read the values back into the ListBox
.
Build a simple text editor. Give it a MenuStrip
with Open and Save commands and a TextBox
. Use an OpenFileDialog
and a SaveFileDialog
to let the user select the file to open and save. (Don't worry about any of the other things a real editor would need to handle, such as locked files and ensuring that the user doesn't close the program with unsaved changes.)
You can find solutions to this lesson's exercises in the Lesson31 folder inside the download available on the book's web site at www.wrox.com
or www.vb-helper.com/24hourvb.html
.