Reading and Writing Files

Among all the fancy data storage methods available under ASP.NET there is still comfort in working with plain vanilla text files. They are trusted friends. ASP.NET supplies file objects that make it very easy to read and write text files.

The System.IO namespace must be imported for working with files. This namespace gives access to the StreamReader and StreamWriter classes for reading and writing text files.

Reading Text Files

The StreamReader class provides several methods for reading text files which are summarized in Figure 10-22.

Dim FileReader As StreamReader

FileReader = File.OpenText(path)
FileLine = FileReader.ReadLine()
FileContents = FileReader.ReadToEnd()

FileReader.Close()
Figure 10-22. General formats for reading text files.

FileReader is a variable that is declared as a StreamReader object. The File class' OpenText() method then assigns the text file located on the path to this FileReader object. The StreamReader's ReadLine() method reads a single line of text from the file, not including the line-break character. The line of text is normally assigned to a string variable for script handling. The StreamReader's ReadToEnd() method reads all the contents of a file including line-break characters. This collection of all lines in the file can be assigned to a string variable. The StreamReader's Close() method is called after finishing with the file.

For the following examples the Books.txt file located in the c:\eCommerce\Databases directory is used. Its layout is shown below along with the first six records in the file.

ID,Type,Title,Author,Price,Qty
DB111,Database,Oracle Database,K. Loney,69.99,10
DB222,Database,Databases in Depth,C. J. Date,29.95,6
DB333,Database,Database Processing,D. Kroenke,136.65,12
DB444,Database,Access Database Design,S. Roman,34.95,25
DB555,Database,SQL Server 2005,P. Debetta,29.99,0
...

Figure 10-23. Contents of Books.txt file.

Reading an Entire Text File

One of the ways to read a text file is to use the ReadToEnd() method to capture the entire file at once. The file is read from beginning to end as a continuous stream of text, ignoring any line-break characters in the file. This method is used in the following example of reading the Books.txt and reporting its contents in a Label control. Note that the output does not differentiate the separate lines of text appearing in the file.

Read Books.txt File:


Figure 10-24. Reading and displaying the Books.txt file as a continuous stream.
<%@ Import Namespace="System.IO" %>

<SCRIPT Runat="Server">

Sub Read_File (Src As Object, Args As EventArgs)

  Dim FileReader As StreamReader
  FileReader = File.OpenText("c:\eCommerce\Databases\Books.txt")
  FileContents.Text = FileReader.ReadToEnd()
  FileReader.Close()

End Sub

</SCRIPT>

<form Runat="Server">

<b>Read Books.txt File: </b>
<asp:Button Text="Read File" OnClick="Read_File" Runat="Server"/>

<p><asp:Label id="FileContents" EnableViewState="False" Runat="Server"/></p>

</form>
Listing 10-25. Code to read and display the Books.txt file as a continuous stream.

First, FileReader is created as a StreamReader object; then the File.OpenText() method is used to connect to the file and assign it to the FileReader. This reader's ReadToEnd() method captures the entire file (minus any line-break characters) and assign it to the FileContents Label for display. An alternative, of course, is to read the file into a script variable for other types of processing. Lastly, the FileReader is closed.

Reading Lines of Text from a File

More often than not, it is necessary to differentiate the separate lines of text appearing in a file. A script, for instance, may process each line individually rather than read the entire file at once. The following example reads the Books.txt file a line at a time, thereby formatting its output to resemble the structure of the file.

Read Books.txt Lines:

Figure 10-25. Reading and displaying the Books.txt file as individual lines.
<%@ Import Namespace="System.IO" %>

<SCRIPT Runat="Server">

Sub Read_Lines (Src As Object, Args As EventArgs)
  
  Dim FileReader As StreamReader
  FileReader = File.OpenText("c:\eCommerce\Databases\Books.txt")
  
  Dim LineIn As String
  LineIn = FileReader.ReadLine()    '-- read initial line
  While LineIn <> Nothing
    FileContents.Text &= LineIn & "<br/>"
    LineIn = FileReader.ReadLine()  '-- read next line
  End While
  FileReader.Close()

End Sub

</SCRIPT>

<form Runat="Server">

<b>Read Books.txt Lines: </b>
<asp:Button Text="Read Lines" OnClick="Read_Lines" Runat="Server"/>

<p><asp:Label id="FileContents" EnableViewState="False" Runat="Server"/></p>

</form>
Listing 10-26. Code to read and display the Personnel.txt file as individual lines.

Consider the general script structure for reading individual lines from a text file. The "look-ahead" reading technique is used to read an initial line from the file (into variable LineIn in this example). Then a While...End While loop is set up to process that line and read the next line at the bottom of the loop. Processing and reading continues until there are no more lines to read.

One of the ways to test for the end of the file is to test for a null line returned from the ReadLine() method. This test is employed in the above example by checking whether variable LineIn contains Nothing. This is an indication that no data lines remain in the file, providing the condition for ending the process-and-read loop.

Within the example loop, the contents of variable LineIn includes the string of text from a line in the file, absent its line-break character. An XHTML <br/> tag is appended to this text, which is concatenated to the output Label to display this individual text line.

End-of-File Markers

The keyword Nothing represents a null character, i.e., a blank line or no-more-lines in the file. If, however, a file contains legitimate blank lines, then another technique needs to be used to indicate the end of the file. Often, a special trailing record containing an end-of-file marker is used. This could be, for example, a line coded as "//EOF" (or any other special characters not likely to begin a legitimate record). Then the condition for ending the processing loop includes a test for this special string.

LineIn = FileReader.ReadLine()
While LineIn <> "//EOF"
  ...process the line
  LineIn = FileReader.ReadLine()
End While
Listing 10-27. Testing for an end-of-file marker.

Splitting Fields into an Array

In the preceding example, entire lines of text are treated as a single entity. No consideration is given to the fact that lines are composed of individual data fields separated by commas. For certain applications, this may not be a consideration. For example, when duplicating a file by reading and writing entire lines of text, it is not important that individual data fields be distinguished. For other applications, however, it may be necessary to decompose the lines into their individual fields.

In the following example, lines from the Books.txt file are broken down into their component fields so they can be formatted for display in an XHTML table.

Read Books.txt Fields:

Figure 10-26. Reading and displaying the data fields from Books.txt.
<%@ Import Namespace="System.IO" %>

<SCRIPT Runat="Server">

Sub Read_File_Fields (Src As Object, Args As EventArgs)

  Dim FileReader As StreamReader
  FileReader = File.OpenText("c:\eCommerce\Databases\Books.txt")
	
  Dim LineIn As String
  Dim FieldArray() As String
  Dim Field As String

  LineIn = FileReader.ReadLine()
  If Not LineIn = Nothing Then
    FieldArray = Split(LineIn, ",")
		
    '-- Display table header
    FileContents.Text &= "<table border=""1"">"
    FileContents.Text &= "<tr style=""background-color:#F0F0F0"">"
    For Each Field in FieldArray
      FileContents.Text &= "<th>" & Field & "</th>"
    Next
    FileContents.Text &= "</tr>"
		
    '-- Display table rows
    LineIn = FileReader.ReadLine()
    While LineIn <> Nothing
      FieldArray = Split(LineIn, ",")
			
      '-- Display a table row
      FileContents.Text &= "<tr>"
      For Each Field in FieldArray
        FileContents.Text &= "<td>" & Field & "</td>"
      Next
      FileContents.Text &= "</tr>"
			
      LineIn = FileReader.ReadLine()
    End While
		
    FileContents.Text &= "</table>"
  End If
  FileReader.Close()

End Sub

</SCRIPT>

<form Runat="Server">

<b>Read Books.txt Fields: </b>
<asp:Button Text="Read File" OnClick="Read_File_Fields" Runat="Server"/>

<p><asp:Label id="FileContents" EnableViewState="False" Runat="Server"/></p>

</form>
Listing 10-28. Code to read and display the data fields from Books.txt.

An input line is separated into its component fields by using the Visual Basic Split() function whose general format is shown below.

array = Split(string, [delimiter])
Figure 10-27. General format for Visual Basic Split() function.

This function tests for a delimiter character to break apart a text string and to assign the individual substrings to an array. The default delimiter is a blank space and does not need to be specified; otherwise, the delimiter character is coded as a string in the function. Then it is a matter of iterating this array to display the individual fields of data. Array elements can be identified by their indexes (array(0), array(1), array(2), etc.), or a For Each...Next loop can be established to iterate all elements of the array.

In the above example, each line from the file is split into array FieldArray and a For Each...Next loop accesses the individual array elements. For instance, when the first line of the file—containing field names—is read into variable LineIn, this string is split into separate elements of FieldArray, which is then iterated to produce a row of column headings for the output table.

...
  LineIn = FileReader.ReadLine()
  If Not LineIn = Nothing Then
   FieldArray = Split(LineIn, ",")

    'Display table header
    FileContents.Text &= "<table border=""1"">"
    FileContents.Text &= "<tr style=""background-color:#F7F7F7"">"
    For Each Field in FieldArray
      FileContents.Text &= "<th>" & Field & "</th>"
    Next
    FileContents.Text &= "</tr>"
    ...
  End If
	...
Listing 10-29. Splitting an input string into an array to produce table headings.

The same technique is used to split individual lines from the file into an array of data fields which are iterated to produce individual table rows.

Writing Text Files

The StreamWriter provides methods for writing text files. These methods are summarized in Figure 10-28.

Dim FileWriter As StreamWriter

FileWriter = File.CreateText(path)
FileWriter = File.AppendText(path)
FileWriter.WriteLine(string)
FileWriter.Write(string)

FileWriter.Close()
Figure 10-28. General formats for writing text files.

FileWriter is a variable that is declared as a StreamWriter object. The File class' CreateText() method assigns the text file located on the path to this FileWriter object. This method creates the text file if it does not exist, and it overwrites the text file if it does exist. The AppendText() method adds lines to an existing file. Again, the file is created if it does not exist.

The StreamWriter's WriteLine(string) method writes a string of text to the file and appends a line-break character. The Write(string) method writes a string of text without a line-break character. This method can be used several times in a row to compose a line in the file before finally writing a line-break character. It also can write a string representing the entire file contents at one time. The StreamWriter's Close() method is called after finishing with the file.

A simple example of creating a new text file and writing three lines to the file is shown in Listing 10-30.

Sub Write_File (Src As Object, Args As EventArgs)

  Dim FileWriter As StreamWriter
  FileWriter = File.CreateText(c:\eCommerce\Databases\NewFile.txt")
  FileWriter.WriteLine("First line of file")
  FileWriter.WriteLine("Second line of file")
  FileWriter.WriteLine("Third line of file")
  FileWriter.Close()

End Sub
Listing 10-30. Code to create a new text file.

Since the WriteLine() method is used, each line is written with a line-break character resulting in a file with three separate lines of text. If the file does not exist, it is created; if the file does exist, it is overwritten. If the subprogram uses the File.AppendText() method rather than the File.CreateText() method, then lines written to the file are added to the end of current lines in the file.

Creating Text Files

It is fairly easy to create a page application that permits users to create text files. All that is required is a text input area for entering lines of text along with a subprogram to append lines to the end of a file.

File Name:

Input Line:   Line added
Figure 10-29. Creating and appending lines to a new text file.
<%@ Import Namespace="System.IO" %>

<SCRIPT Runat="Server">

Sub Create_File (Src As Object, Args As EventArgs)

  If FileName.Text <> "" Then
    If Not File.Exists("c:\eCommerce\Databases\" & FileName.Text)
      Dim NewFile As StreamWriter
      NewFile = File.CreateText("c:\eCommerce\Databases\" & FileName.Text)
      NewFile.Close()
      InputPanel.Visible = True
    Else
      FileExistsMsg.Text = "File already exists. Not created."
    End If
  End If

End Sub

Sub Add_To_File (Src As Object, Args As EventArgs)

  Dim FileWriter As StreamWriter
  FileWriter = File.AppendText("c:\eCommerce\Databases\" & FileName.Text)
  FileWriter.WriteLine(FileLine.Text)
  FileWriteMsg.Text = "Line added"
  FileLine.Text = ""
  FileWriter.Close()

End Sub

</SCRIPT>

<form Runat="Server">

File Name: <asp:TextBox id="FileName" Runat="Server"/>
<asp:Button Text="Create File" OnClick="Create_File" Runat="Server"/>
<asp:Label id="FileExistsMsg" Runat="Server"
  EnableViewState="False" ForeColor="#FF0000"/><br/><br/>

<asp:Panel id="InputPanel" Visible="False" Runat="Server">
  Input Line: <asp:TextBox id="FileLine"
    EnableViewState="False" Runat="Server"/>
  <asp:Button Text="Add To File" Runat="Server"
    OnClick="Add_To_File"/>
  <asp:Label id="FileWriteMsg" Runat="Server"
    EnableViewState="False" ForeColor="#FF0000"/>
</asp:Panel>

</form>
Listing 10-31. Code to create a new text file.

A textbox is presented for the user to enter a new file name. If the file does not current exist, it is created and the text input area is displayed by making its enclosing Panel visible. Each input line is appended to those already added to the file.

Database Backup

File creation, reading, and writing methods are illustrated by adding a database backup feature for the BooksDB.mdb database. Creation of a text file of records from the Books table can be used to reload the table if necessary. The following example has its save and delete routines disabled.

Records from the Books table are input and formatted within a text area for visual verification of file contents. These records are then saved as text file Books.txt to the c:\eCommerce\Databases folder. The saved file can be visually verified by opening and displaying it.

BooksDB.mdb Backup


Figure 10-30. Reading, writing, and deleting a text file.

Page Layout

The page is formatted with a row of buttons along with two display areas. A multiline <asp:TextBox> holds the records from the Books table, formatted for text output. An <asp:Label> provides an area for displaying the saved file. Initially, this file display Label is hidden.

<h3>BooksDB.mdb Backup</h3>

<asp:Button Text="Load Table" OnClick="Load_Table" Runat="Server"/>
<asp:Button Text="Save Table" OnClick="Save_Table" Runat="Server"/>
<asp:Button Text="Show File" OnClick="Show_File" Runat="Server"/>
<asp:Button Text="Delete File" OnClick="Delete_File" Runat="Server"/>
<asp:Label id="Message" ForeColor="#FF0000" Runat="Server"
  EnableViewState="False"/><br/>

<asp:TextBox id="FileBox" Runat="Server"
  TextMode="MultiLine" 
  Columns="70"
  Rows="20"
  Font-Size="8pt"
  Font-Name="Courier New"
  Wrap="False"/>

<asp:Panel id="FilePanel" Visible="False"  Runat="Server"
Width="510px" Height="300px" BorderStyle="Solid" BorderWidth="1px"
ScrollBars="Auto">

  <asp:Label id="FileDisplay" Runat="Server"/>

</asp:Panel>
Listing 10-32. Server controls to read, write, and delete a text file.

Loading the Books Table

The "Load Table" button calls the Load_Table subprogram to retrieve all records from the Books table and to format them as text strings for writing to the display area. These formatted records are displayed in the multiline TextBox.

<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.IO" %>

<SCRIPT Runat="Server">

Sub Load_Table (Src As Object, Args As EventArgs)

  Dim DBConnection As OleDbConnection
  Dim DBCommand As OleDbCommand
  Dim DBReader As OleDbDataReader
  Dim SQLString As String
  Dim RecordString As String

  DBConnection = New OleDbConnection( _
    "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=" & Server.MapPath("../Databases/BooksDB.mdb"))
  DBConnection.Open()
  SQLString = "SELECT * FROM Books ORDER BY BookID"
  DBCommand = New OleDbCommand(SQLString, DBConnection)
  DBReader = DBCommand.ExecuteReader()
  FileBox.Text = ""
  While DBReader.Read()
    RecordString = ""
    RecordString &= DBReader("BookID") & "|"
    RecordString &= DBReader("BookType") & "|"
    RecordString &= DBReader("BookTitle") & "|"
    RecordString &= DBReader("BookAuthor") & "|"
    RecordString &= DBReader("BookDescription") & "|"
    RecordString &= DBReader("BookPrice") & "|"
    RecordString &= DBReader("BookQty")
    FileBox.Text &= RecordString & Chr(10)
  End While
  DBReader.Close()
  DBConnection.Close()
  FileBox.Visible = True
  FilePanel.Visible = False
  Message.Text = "Table loaded"

End Sub

</SCRIPT>
Listing 10-33. Script to display a text file.

The individual fields of a Books record are concatenated into variable RecordString to compose a display line. This variable is then appended to the TextBox display area. In order to visually and physically separate the data fields along a line, a special delimiter character is used. In this example, the "|" (pipe) character is written since this character is not likely to appear as an actual character in any of the fields. A line-break character—Chr(10)—is added to the end of the line to produce a line break in the TextBox and also in the text file that is written from the TextBox.

Writing the BooksBK.txt File

The formatted Books records appearing in the multiline TextBox are written to a BooksBK.txt backup file by clicking the "Save Table" button. This button click calls the Save_Table subprogram.

Sub Save_Table (Src As Object, Args As EventArgs)

  If FileBox.Text <> "" Then
    Dim FileWriter As StreamWriter
    FileWriter = File.CreateText(Server.MapPath("../Databases/BooksBK.txt"))
    FileWriter.Write(FileBox.Text)
    FileWriter.Close()
    Message.Text = "File saved"
  Else
    Message.Text = "No records to save"
  End If

End Sub
Listing 10-34. Script to write a text file.

The File.CreateText() method is used to overwrite an existing file or to create a new file if BooksBK.txt does not exist. The StreamWriter's Write() method is used to write the contents of the TextBox to the file all at one time. The resulting file is comprised of separate lines of text because the line-break character, Chr(10), is appended to each line when filling the TextBox. Then the file is closed. No file is written if the TextBox does not contain the records from the Books table.

Showing the BooksBK.txt File

The "Show File" button is clicked to retrieve the saved file and display it for visual verification. This button calls the Show_File subprogram.

Sub Show_File (Src As Object, Args As EventArgs)

  If File.Exists(Server.MapPath("../Databases/BooksBK.txt")) Then
    Dim FileReader As StreamReader
    Dim LineIn As String
    Dim FieldArray() As String
    Dim Item As String
    
    FileReader = File.OpenText(Server.MapPath("../Databases/BooksBK.txt"))
    FileDisplay.Text = ""
    LineIn = FileReader.ReadLine()
    While LineIn <> ""
      FieldArray = Split(LineIn, "|")
      For Each Item in FieldArray
        FileDisplay.Text &= Item & "<br/>"
      Next
      FileDisplay.Text &= "<br/>"
      LineIn = FileReader.ReadLine()
    End While
    FileReader.Close()
    FileBox.Visible = False
    FilePanel.Visible = True
  Else
    Message.Text = "File does not exist"
  End If
  
End Sub
Listing 10-35. Script to display a text file.

This subprogram uses the look-ahead method of reading through the BooksBK.txt file. Each line of the file is split into array FieldArray() so that individual fields can be handled separately. In this case, each field is written as a separate line to the FileDisplay output Label. After reading through and formatting the entire file, the FilePanel enclosing the Label is made visible for viewing the formatted file.

Deleting the BooksBK.txt File

Finally, subprogram Delete_File can be called to delete the BooksBK.txt file. This script uses the File.Delete() method of the File class to delete the file, after making sure that the file exists.

Sub Delete_File (Src As Object, Args As EventArgs)

  If File.Exists(Server.MapPath("../Databases/BooksBK.txt")) Then
    File.Delete(Server.MapPath("../Databases/BooksBK.txt"))
    Message.Text = "File deleted"
    FileBox.Text = ""
    FileBox.Visible = True
    FileDisplay.Visible = False
  Else
    Message.Text = "File does not exist"
  End If

End Sub
Listing 10-36. Script to delete a file.