Writing To Text Files

Level:
Level1

VB.NET provides multiple ways to save program data out to a file. This VB Tutorial will walk you through several different ways to easily save your data to a simple text file. This is by far the most straight forward way to serialize data so that your VB program can later read it back in. Below you will learn how to write to files using both a fixed format or a delaminated format. If you don’t know what this means or why you would choose one over the other please read on and it will make sense.

In another post (about Reading Text Files In VB.NET), we saw how to use the FileStream and StreamReader classes of the System.IO namespace to read a text file in both fixed-length and pipe-delimited formats. We also saw how to use the Input function of the Microsoft.VisualBasic namespace to easily read a comma-delimited file that also contained fields enclosed in quotes.

In this tutorial we will see how to use the FileStream and StreamWriter classes of the System.IO namespace to write a text file in both fixed-length and pipe-delimited formats. We will also see how to use the WriteLine function of the Microsoft.VisualBasic namespace to easily create a comma-delimited file that contains text fields enclosed in quotes; we will also see how to use the PrintLine function of the MS.VB namespace to create a fixed-length file, noting the similarities and differences between that and the StreamWriter technique.

As in the previous section, the file that will be used for all examples in this section is a simplified employee file, which consists of the following fields:

Field Data Type*
Employee Name String
Department Number Integer
Job Title String
Hire Date Date
Hourly Rate Single

*Please note that the data types for these fields are the data types of the variables into which these fields will be stored.  In the text file, all fields will be represented as a string of characters.

Example 1: Writing a Text File with Fixed-Length Fields

For the fixed-length file, we want to write the records in the following format:

Columns Field / Notes
1-20 Employee Name (last name first, 20 characters, space-filled on the right)
21-24 Department Number (up to 4 digits, space-filled on the left)
25-29 (unused – should contain blank spaces)
30-50 Job Title (21 characters, space-filled on the right)
51-60 Hire Date (month/day/year format, 10 characters, space-filled on the right)
61-65 Hourly Rate (a value between 0 and 99.99, occupies 5 positions, space-filled on the left)

In this example program, the user will be prompted to enter each field on the console, one-by-one (employee name, then department, job title, hire date, and hourly rate). As the user enters each field, the program will check to make sure the data is valid (and if invalid, will show a message and re-prompt for that same field). When all five fields for a record have been entered, the program will write a fixed-length record to the output file and start all over again with the prompts for the next record, beginning with the employee name. If the user presses the Enter key without entering a value for the employee name, this signals the program that the user is done, and the program will end.

A screen-shot of a sample run, where the user has entered two records, is shown below:

image

Looking at the output file in a text editor such as Notepad, we see:

FARLEY,FRANK   123   DBA         1/1/2001  40.00
GARFIELD,GARY  43    IT MANAGER  3/5/1992  60.00

The code for the program is shown below. Note that Sub Main is fairly streamlined, due to the fact that the prompts and data validation for each field are contained in their own functions (GetEmployee, GetDepartment, GetJobTitle, GetHireDate, and GetHourlyRate) which are invoked by Sub Main when needed.

Imports System.IO 
 
Module Module1 
 
    Sub Main()
 
        Dim strFileName AsString = My.Application.Info.DirectoryPath _
                          & "\empout_fixed.txt"
        Dim objFS AsNew FileStream(strFileName, FileMode.Create, FileAccess.Write)
        Dim objSW AsNew StreamWriter(objFS)
        Dim strEmpName AsString
        Dim intDeptNbr AsInteger
        Dim strJobTitle AsString
        Dim dtmHireDate AsDate
        Dim sngHrlyRate AsSingle
 
        ' Set up an "input loop" to prompt the user for data ...
        ' "Priming" input:
        strEmpName = GetEmployeeName()
 
        ' The loop will continue until the user enters a zero-length string for the 
        ' employee name ...
        DoUntil strEmpName = ""
            ' Prompt the user for each field ...
            intDeptNbr = GetDepartment()
            strJobTitle = GetJobTitle()
            dtmHireDate = GetHireDate()
            sngHrlyRate = GetHourlyRate()
 
            ' Write out the record to the file ...
            objSW.WriteLine(strEmpName.PadRight(20) & _
                            intDeptNbr.ToString.PadLeft(4) & _
                            Space(5) & _
                            strJobTitle.PadRight(21) & _
                            Format(dtmHireDate, "M/d/yyyy").PadRight(10) & _
                            Format(sngHrlyRate, "Standard").PadLeft(5))
            Console.WriteLine("Record was written to the output file.")
            Console.WriteLine("")
            ' Start a new record by prompting for the employee name ...
            strEmpName = GetEmployeeName()
        Loop
 
        objSW.Close()
        Console.WriteLine("")
        Console.WriteLine("File creation complete. Press Enter to close this window.")
        Console.ReadLine()
 
    EndSub
 
    PrivateFunction GetEmployeeName() AsString
        Dim strTest AsString
        Dim blnValidInput AsBoolean
 
        Do
            Console.Write("Enter Employee Name (1-20 characters / nothing to quit): ")
            strTest = Console.ReadLine()
            strTest.Trim()
            blnValidInput = True
            If strTest.Length > 20 Then
                blnValidInput = False
                Console.WriteLine("Invalid employee name.")
            EndIf
        LoopUntil blnValidInput
 
        Return (strTest)
    EndFunction
 
    PrivateFunction GetDepartment() AsInteger
        Dim strTest AsString
        Dim blnValidInput AsBoolean
        Dim intX AsInteger
        Do
            Console.Write("Enter Dept (1 to 4 digits): ")
            strTest = Console.ReadLine()
            blnValidInput = True
            If strTest.Length < 1 Or strTest.Length > 4 Then
                blnValidInput = False
            Else
                For intX = 0 To (strTest.Length - 1)
                    IfNot (Char.IsDigit(strTest.Chars(intX))) Then
                        blnValidInput = False
                        ExitFor
                    EndIf
                Next
            EndIf
            IfNot blnValidInput Then
                Console.WriteLine("Invalid department number.")
            EndIf
        LoopUntil blnValidInput
        Return (CInt(strTest))
    EndFunction
 
    PrivateFunction GetJobTitle() AsString
        Dim strTest AsString
        Dim blnValidInput AsBoolean
 
        Do
            Console.Write("Enter Job Title (1 to 21 characters): ")
            strTest = Console.ReadLine()
            blnValidInput = True
            If strTest.Length < 1 Or strTest.Length > 21 Then
                Console.WriteLine("Invalid job title.")
                blnValidInput = False
            EndIf
        LoopUntil blnValidInput
        Return (strTest)
    EndFunction
 
    PrivateFunction GetHireDate() AsDate
        Dim strTest AsString
        Dim blnValidInput AsBoolean
 
        Do
            Console.Write("Enter Hire Date (month/day/year): ")
            strTest = Console.ReadLine()
            blnValidInput = True
            IfNot IsDate(strTest) Then
                Console.WriteLine("Invalid hire date.")
                blnValidInput = False
            EndIf
        LoopUntil blnValidInput
 
        Return (CDate(strTest))
    EndFunction
 
    PrivateFunction GetHourlyRate() AsSingle
        Dim strTest AsString
        Dim blnValidInput AsBoolean
 
        Do
            Console.Write("Enter Hourly Rate (0 to 99.99): ")
            strTest = Console.ReadLine()
            blnValidInput = True
 
            IfNot IsNumeric(strTest) Then
                blnValidInput = False
            ElseIf Val(strTest) < 0 Or Val(strTest) > 99.99 Then
                blnValidInput = False
            EndIf
 
            IfNot blnValidInput Then
                Console.WriteLine("Invalid hourly rate.")
            EndIf
        LoopUntil blnValidInput
 
        Return (CSng(strTest))
    EndFunction
End Module 

A synopsis of the code follows:

Note that first, your program must import the System.IO namespace. In the Main procedure, the variable to hold the full path and filename of the output file is declared and initialized (note that the location of the file is My.Application.Info.DirectoryPath which, as discussed in the previous section, refers to the directory in which your program is running, normally \bin\Debug in your application directory). The name of the file is "empout_fixed.txt". The FileStream object is the established to hold a reference to the file (note that it is declared in "Create" mode with "Write" access). Then, the StreamWriter object is declared.

The StreamWriter class is used to write a stream of characters. In the .NET framework, a stream, in general terms, is the flow of data from one location to another. In the case of these examples, a stream refers to the text file that will be processed by the sample programs. The syntax for declaring a StreamWriter object is:

       Dim variable As New StreamReader(stream) 

where stream is an object representing the stream of characters to be written (in this case a text file).

Variables to hold the data fields are then declared. The processing starts with a "priming" input outside the main loop. This calls the GetEmployeeName function which will prompt the user for the employee name and return the string entered. The loop's termination condition tests whether the name entered is a zero-length string. As long as the user entered "something", the loop will continue. In the loop, prompts are made and input is validated and returned for the department, job title, hire date, and hourly rate fields by calling the GetDepartment, GetJobTitle, GetHireDate, and GetHourlyRate functions, respectively. The fixed-length record is written to the file by the WriteLine method of the StreamWriter object (which was defined with the variable name objSW). The string that is passed to the method is a concatenation of the variables holding the values for the data fields, padded and formatted appropriately. A message is displayed on the console telling the user that the record was written, then the GetEmployeeName function is called as the last statement of the loop, which prompts the user for the employee name, for another possible pass through the loop to write another record. When the user finally responds to the employee name prompt with just the Enter key, the loop ends, we close the StreamWriter object and let the user know the writing of the file is complete.

Download this for VB.NET example: Writing Fixed Length Example


Example 2: Writing a Text File with Pipe-Delimited Fields

In the second example, a file with pipe-delimited fields is produced. Using the same data entered in Example 1, an inspection of the output file in a text editor such as Notepad would show:

FARLEY,FRANK|123|DBA|1/1/2001|40
GARFIELD,GARY|43|IT MANAGER|3/5/1992|60

The code for the Example 2 program is identical to that of Example 1, except that the output file is named "empout_pipe.txt":

        Dim strFileName AsString = My.Application.Info.DirectoryPath _
                          & "\empout_pipe.txt"

and in the objSW.WriteLine statement, the string that is passed consists of the variables holding the values for the data fields, formatted as necessary, concatenated with the pipe character ("|"):

            objSW.WriteLine(strEmpName & "|" & _
                            intDeptNbr.ToString & "|" & _
                            strJobTitle & "|" & _
                            Format(dtmHireDate, "M/d/yyyy") & "|" & _
                            sngHrlyRate.ToString)

Download the VB.NET code for this example: Pipe Deliminated File Writing


Example 3: Writing a Text File with Comma-Delimited Fields (String Fields Enclosed in Quotes)

In the third example, a file with comma-delimited fields is produced. String fields in this file will also be enclosed in quotes. Using the same data entered in Example 1, an inspection of the output file in a text editor such as Notepad would show:

"FARLEY,FRANK",123,"DBA","1/1/2001",40
"GARFIELD,GARY",43,"IT MANAGER","3/5/1992",60

This example uses the Microsoft.VisualBasic namespace functions for all I/O, so the System.IO namespace need not be included. The function that produces the output record is WriteLine (not to be confused with the WriteLine method of the System.IO StreamWriter class – in the MS.VB namespace, the WriteLine function is a retooled version of the Write statement from pre-.NET versions of Visual Basic).

The syntax of the MS.VB namespace WriteLine function, as it is used in this example is:

       WriteLine (filenumber[, expression1[, expression2 ...[, expression n]]]) 

where filenumber is the file number referenced used to open the file with the FileOpen function, and expression1 through expression n is the list of expressions (variables, constants, etc.) that are to be written to the output file. When executed, the items in the expression list are automatically written to the file with commas separating the expressions for each other; and string items are automatically enclosed in quotes.

It should be noted that files written with the WriteLine function are most commonly read back with the Input function. Also note that while we are treating the Hire Date field as a string, the WriteLine function can write a "date" expression to a text file, in which case the date would be written to the file in yyyy-mm-dd format and would be enclosed in pound signs (#) rather than quotes; and if the file is read back with the Input function, the Input function would recognize a field enclosed with pound signs as a date data type.

The code for the Sub Main portion of Example 3 is shown below:

	Sub Main()
 
        Dim strFileName AsString = My.Application.Info.DirectoryPath _
                          & "\empout_comma.txt"
        Dim intFileNbr AsInteger = FreeFile()
        Dim strEmpName AsString
        Dim intDeptNbr AsInteger
        Dim strJobTitle AsString
        Dim dtmHireDate AsDate
        Dim sngHrlyRate AsSingle
 
        FileOpen(intFileNbr, strFileName, OpenMode.Output, OpenAccess.Write)
 
        ' Set up an "input loop" to prompt the user for data ...
        ' "Priming" input:
        strEmpName = GetEmployeeName()
 
        ' The loop will continue until the user enters a zero-length string for the 
        ' employee name ...
        DoUntil strEmpName = ""
            ' Prompt the user for each field ...
            intDeptNbr = GetDepartment()
            strJobTitle = GetJobTitle()
            dtmHireDate = GetHireDate()
            sngHrlyRate = GetHourlyRate()
 
			' Write out the record to the file ...
            WriteLine(intFileNbr, _
                      strEmpName, _
                      intDeptNbr, _
                      strJobTitle, _
                      Format(dtmHireDate, "M/d/yyyy"), _
                      sngHrlyRate)
            Console.WriteLine("Record was written to the output file.")
            Console.WriteLine("")
 
			' Start a new record by prompting for the employee name ...
            strEmpName = GetEmployeeName()
        Loop
 
        FileClose(intFileNbr)
 
        Console.WriteLine("")
        Console.WriteLine("File creation complete. Press Enter to close this window.")
        Console.ReadLine()
    EndSub

    The GetEmployee, GetDepartment, GetJobTitle, GetHireDate, and GetHourlyRate functions referenced in code above are exactly the same as in the previous examples.

A synopsis of the code follows:

The flow of this program is identical to that of the previous examples, but we are using all MS.VB namespace functions instead of the System.IO FileStream and StreamWriter classes. In the Main procedure, the variable to hold the full path and filename of the output file is declared and initialized (in this example, the filename is "empout_comma.txt"). An Integer  variable to hold the filenumber is declared and initialized with the FreeFile function. Variables to hold the data fields are then declared. The file is then opened with the FileOpen function using output mode with write access.

As in the previous examples, the processing starts with a "priming" input outside the main loop. This calls the GetEmployeeName function which will prompt the user for the employee name and return the string entered. The loop's termination condition tests whether the name entered is a zero-length string. As long as the user entered "something", the loop will continue. In the loop, prompts are made and input is validated and returned for the department, job title, hire date, and hourly rate fields by calling the GetDepartment, GetJobTitle, GetHireDate, and GetHourlyRate functions, respectively. The comma-delimited record is then written to the file with the WriteLine function, passing it the filenumber followed by the list of variables holding the data fields. A message is displayed on the console telling the user that the record was written, then the GetEmployeeName function is called as the last statement of the loop, which prompts the user for the employee name, for another possible pass through the loop to write another record. When the user finally responds to the employee name prompt with just the Enter key, the loop ends, we close the file using the FileClose function, and let the user know the writing of the file is complete.

Donwload the VB.NET source for this example: Write Comma Delimited Files


Example 4: Writing a Text File with Fixed-Length Fields (Using the PrintLine Function)

This example uses the MS.VB namespace PrintLine function to produce a fixed-length file. The output is identical to that produced in the first example:

FARLEY,FRANK         123     DBA                  1/1/2001  40.00
GARFIELD,GARY         43     IT MANAGER           3/5/1992  60.00

The syntax of the MS.VB namespace PrintLine function, as it is used in this example is:

       PrintLine (filenumber[, expression1[, expression2 ...[, expression n]]]) 

where filenumber is the file number referenced used to open the file with the FileOpen function, and expression1 through expression n is the list of expressions (variables, constants, etc.) that are to be written to the output file. However, unlike the WriteLine function, no automatic formatting of the data occurs; each item in the expression list is written adjacent to each other with no added separation characters or quotes. In that PrintLine is a retooled version of the Print statement found in pre-.NET versions of VB, there are two built-in functions that can be used within the PrintLine expression list: TAB and SPC.

SPC(n) simply inserts n number of blank spaces into the output line being built. So the statement PrintLine (1, "ABC", SPC(5), "DEF") would result in a line written to the output file containing "ABC", followed by five blank spaces, followed by "DEF".

TAB(n) is actually a directive that tells PrintLine to position the next output item at position n in the output line. So the statement PrintLine (1, "ABC", TAB(20), "DEF") would result in a line written to the output file containing "ABC", followed by 16 blank spaces, followed by "DEF". This is because first, "ABC" would be written, occupying the first three positions – then TAB(20) says to skip to position 20 in the output line and write "DEF". So 16 positions needed to be bypassed (actually space-padded) to give the 19 positions prior to the 20th where "DEF" would start.

The code for the Example 4 program is identical to that of Example 3, except that the output file is named "empout_fixed_pl.txt":

        Dim strFileName AsString = My.Application.Info.DirectoryPath _
                          & "\empout_fixed_pl.txt"

and the PrintLine function is used instead of the WriteLine function:

	PrintLine(intFileNbr, _
                      strEmpName, _
                      TAB(21), _
                      intDeptNbr.ToString.PadLeft(4), _
                      SPC(5), _
                      strJobTitle, _
                      TAB(51), _
                      Format(dtmHireDate, "M/d/yyyy"), _
                      TAB(61), _
                      Format(sngHrlyRate, "Standard").PadLeft(5))

Download the VB.NET code for this example: Fixed Length With PrintLine

This article was original written by The VB Programmer.

If you enjoyed this post, subscribe for updates (it's free)