Text Streams*

Some of the most useful VB.NET file handling objects and commands are demonstrated here, including a program to merge two ordered files into one ordered file.

This first example illustrates the use of the VB.NET StreamReader object which can be used to read a text file line by line. Notice that the System.IO namespace is imported above the form class declaration, because this is where the StreamReader class resides.

When a StreamReader object is instantiated, its constructor is passed the path and name of the file as a string. The full absolute path can be specified, but in the example below the SpecialDirectories.MyDocuments property is used to obtain the path of the text file which is presumed to be in the current user’s Documents folder.

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ReadFileLineByLine()
    End Sub

    Sub ReadFileLineByLine()

        Dim objStreamReader As StreamReader
        Dim strLine As String

        'Pass the file path and the file name to the StreamReader constructor
        objStreamReader = New StreamReader(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\sourcefile.txt")

        'Read items until you reach the end of the file
        Do While Not objStreamReader.EndOfStream
            strLine = objStreamReader.ReadLine
            MsgBox(strLine)
        Loop

        'Close the file
        objStreamReader.Close()

    End Sub

End Class

The following code makes use of a StreamWriter object to write to a text file.

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        WriteToFile()
    End Sub

    Sub WriteToFile()

        Dim objStreamWriter As StreamWriter

        'Pass the file path and the file name to the StreamWriter constructor
        'The optional Append = True parameter specifies an existing file should not be overwritten
        objStreamWriter = New StreamWriter(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\destinationfile.txt", True)

        'Write a line of text
        objStreamWriter.WriteLine("Hello World")

        'Write a second line of text
        objStreamWriter.WriteLine("From a StreamWriter object")

        'Close the file
        objStreamWriter.Close()

    End Sub

End Class

The following code puts the StreamReader and the StreamWriter together to copy text line by line from one text file to another.

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        CopyFileLineByLine()
    End Sub

    Sub CopyFileLineByLine()

        Dim objStreamReader As StreamReader
        Dim objStreamWriter As StreamWriter

        Dim strLine As String

        'Pass the file paths and the file names to the constructors
        objStreamReader = New StreamReader(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\sourcefile.txt")
        objStreamWriter = New StreamWriter(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\destinationfile.txt")

        'Read and write items until you reach the end of the source file
        Do While Not objStreamReader.EndOfStream
            strLine = objStreamReader.ReadLine
            objStreamWriter.WriteLine(strLine)
        Loop

        'Close the files
        objStreamReader.Close()
        objStreamWriter.Close()

    End Sub

End Class

This final program merges two ordered files to produce a third ordered file. This process is very similar to that used to merge two ordered lists together as in a merge sort.

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Call Merge2Files()
    End Sub

    Sub Merge2Files()
        'Merges two ordered files, file1 and file2
        'Creates or overwrites file3 as new ordered file

        Dim file1 As StreamReader
        Dim file2 As StreamReader
        Dim file3 As StreamWriter

        file1 = New StreamReader(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\file1.txt")
        file2 = New StreamReader(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\file2.txt")
        file3 = New StreamWriter(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\file3.txt", True)

        Dim iCurrentItem1 As Integer
        Dim iCurrentItem2 As Integer

        If (file1.EndOfStream) Or (file2.EndOfStream) Then    'one file is empty
            If file1.EndOfStream Then  'file1 is empty
                'copy the rest of file2 to file3
                Do While Not file2.EndOfStream
                    iCurrentItem2 = file2.ReadLine
                    file3.WriteLine(iCurrentItem2)
                Loop
            Else    'file2 is empty
                'copy the rest of file1 to file3
                Do While Not file1.EndOfStream
                    iCurrentItem1 = file1.ReadLine
                    file3.WriteLine(iCurrentItem1)
                Loop
            End If
        Else                'both files are not empty
            iCurrentItem1 = file1.ReadLine
            iCurrentItem2 = file2.ReadLine
            Do
                'compare current item from file1 with that from file2
                If iCurrentItem1 < iCurrentItem2 Then
                    'write smallest item to file3
                    'read new item from file1 if there is one
                    'otherwise copy the rest of file2 to file3
                    file3.WriteLine(iCurrentItem1)
                    If Not file1.EndOfStream Then
                        iCurrentItem1 = file1.ReadLine
                    Else
                        file3.WriteLine(iCurrentItem2)
                        Do While Not file2.EndOfStream
                            iCurrentItem2 = file2.ReadLine
                            file3.WriteLine(iCurrentItem2)
                        Loop
                        Exit Do
                    End If
                Else
                    'iCurrentItem2 in file2 is smaller; write it to file3
                    'and read new iCurrentItem2 provided there is any
                    'otherwise copy the rest of file1 to file3
                    file3.WriteLine(iCurrentItem2)
                    If Not file2.EndOfStream Then
                        iCurrentItem2 = file2.ReadLine
                    Else
                        file3.WriteLine(iCurrentItem1)
                        Do While Not file1.EndOfStream
                            iCurrentItem1 = file1.ReadLine
                            file3.WriteLine(iCurrentItem1)
                        Loop
                        Exit Do
                    End If
                End If
            Loop
        End If

        file1.Close()
        file2.Close()
        file3.Close()

        MsgBox("done")

    End Sub

End Class

Try this: Compress a File (difficulty level: hard)

When you have mastered the use of the StreamReader and the StreamWriter objects, you could try to write a program to compress a simple text file as follows:

Scan the text in a source file and write each word once into a new text file called words.txt.  The words file should contain every word that occurs in the source file, but only once.  At the same, time write into a new text file called positions.txt, that contains numbers to indicate the positions of each word in the source file.  You should start with a single sentence in your source file; you need concern yourself  with letter case or punctuation to begin with.

For example, if your source file was called source.txt and it contained the text…

ASK NOT WHAT YOUR COUNTRY CAN DO FOR YOU BUT WHAT YOU CAN DO FOR YOUR COUNTRY

…then your program would generate the following two text files:

When you have this working, write a program to recreate the original text file from words.txt and positions.txt.