StreamReader

Hello,

I’m trying to create a program will supply information for variables from a text file, so that as the possibilities change, a simple text file will need to be amended, rather than rewriting the original code. I am reading about FileStream and StreamReader, which seem like just the ticket.

For instance, if I wanted to populate a TextBox with items I wrote in a text file, such as:

Tom

Mike

Jim

Jean

I threw together a sub like this:

------------------------------

Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click

Dim objFS As FileStream

Dim objSR As StreamReader

Dim TextSays As String

objFS = New FileStream("C:\test\test.txt", FileMode.Open, FileAccess.Read)

objSR = New StreamReader(objFS)

TextSays = objSR.ReadToEnd

TextBox1.Text = TextSays

End Sub

-------------------------------

This works perfect. Now, I need the ability to categorize my text file. For instance:

[my family start]

Tom

Mike

Jim

Jean

[my family end]

[your family start]

Bob

Dave

Ted

Steve

[your family end]

I am trying to figure out how to tell the streamreader to start reading in one category, and finish reading at the end of that category. My end result will be a form that I design to have every possible category available on the form, but the items listed for each category to be easily changed or added to by the end user via a simple text file.

Any suggestions would be appreciated.



Answer this question

StreamReader

  • AlexJD

    M Nicholas,

    I think SJ had a point. I believe he was suggesting a way to simplify..

    in a real way, the endmarker doesn't signify anything the the begin marker or EOF wouldn't signify.



  • _Othello_

    You can do it that way and read the entire file in and then try processing it using string / array functionality but again you still have to determine the start and stop points.

    I only continued using the streamreader as this is what you'd done at the initial code sample and title of the thread but if you are reading the entire contents in and then processing them in memory you can load the entire contents of the file into a string using a single line.

    dim s as string = My.Computer.FileSystem.ReadAllText (<FileName>)

    which will read the entire contents of the file into the string variable s. Then you could split the string as your doing and write a algorithm to loop through the array elements. It would be pretty similar to the Streamreader looping process but use the array.

    There are possible advantages / disadvantages

    1. You load the entire file into memory (which could be ok for a small amount of items but with a huge amount of items this could suck up memory)

    2. Accessing memory is potential quicker than accessing disk. (How frequently are you doing this action as if its occuring like 100's or 1000's of times then disk access you may notice the difference between file and memory access)

    3. Is this file contents or array changing frequently during the running of the application and do they need to be kept in sync. Are you modifying the item and then want it reflected immediately afterwards.

    All issues to consider....


  • Dae Yeon Jo

    It works

    My only comment on it is you are physically adding every single item line in the families preceeding the actually family you want to load and then clearing these when you find the family you really want to populate.

    Populating listboxes it reletively slow for large amounts of items. Even though you are physically only wanting say 4 people loaded - if we are family 1000 we may have populate 6000 (4 people + End String + Start Strings) only to remove all of these items to populate 4 items.

    So you may find that the performance seriously drops of for large numbers of families.


  • AJOY KUMAR

    Spotty~

    Without boring you with a lengthy explanation of the program I am constructing (hence the simplistic “family” example), the software is for my wife’s business. I anticipate having 4 or 5 categories, the largest of which will have 20 items (the smallest, maybe 3).

    The crux of the issue though, is that one of the categories will be employees (of which there is a normal amount of turnover). So my plan is to have any part of the software that deals with a list that may be in flux, to fill it’s variables via an easy to amend text file. This way, my (less than computer savvy) wife can easily update the software variables herself.

    Thanks again for helping me (twice now) with this venture into writing my own software. I truly appreciate it.

    Mike


  • DDressel

    I took your concerns to heart and added something similar to what you were doing in your original code.

    ----------------------------

    Dim objFS As New FileStream("C:\test\test.txt", FileMode.Open, FileAccess.Read)

    Dim objSR As New StreamReader(objFS)

    Dim TextSays As String

    Dim StartString As String = "[Start family:B]" 'category start marker

    Dim EndString As String = "[End family:B]" 'category end marker

    Dim blnFound As Boolean 'True or False that category start was reached

    Do While Not objSR.EndOfStream

    TextSays = objSR.ReadLine

    If TextSays = StartString Then 'loops through list until category start maker if found

    blnFound = True

    If blnFound = True Then 'if marker is found...

    Exit Do 'exit the loop

    End If

    End If

    Loop

    Do While Not objSR.EndOfStream

    TextSays = objSR.ReadLine 'reads first line after previous loop (StringStart)

    ListBox1.Items.Add(TextSays) 'adds to ListBox1

    If TextSays = StartString Then 'category start marker

    ListBox1.Items.Remove(TextSays) 'clears category start maker from list

    ElseIf TextSays = EndString Then 'finds end of category marker

    ListBox1.Items.Remove(TextSays) 'removes end marker from list

    Exit Do 'exits do loop before entering another category

    End If

    Loop

    objFS.Close()

    ------------------------

    I think this is the ticket!


  • developer74

    The performance probably wont be a great issue for the numbers you are talking about - but I just commented on this as others may see this use it as an example and complain when they try and populate 1000 groupings and find it is pretty slow.


  • Krystan Honour

    Hey Spotty~

    (Still goofing around with possibilities)

    What do you think about this

    (test.txt File)

    [Start family:A]
    Mike
    Jim
    Tom
    Jean
    [End family:A]

    [Start family:B]
    Steve
    Dave
    Ted
    Bob
    [End family:B]

    ---------------------------------

    Dim objFS As FileStream

    Dim objSR As StreamReader

    Dim TextSays As String

    objFS = New FileStream("C:\test\test.txt", FileMode.Open, FileAccess.Read)

    objSR = New StreamReader(objFS)

    Dim StartString As String = "[Start family:B]"

    Dim EndString As String = "[End family:B]"

    Do While Not objSR.EndOfStream

    TextSays = objSR.ReadLine

    ListBox1.Items.Add(TextSays)

    If TextSays = StartString Then

    ListBox1.Items.Clear()

    ElseIf TextSays = EndString Then

    ListBox1.Items.Remove(TextSays)

    Exit Do

    End If

    Loop

    ------------------------

    This particular sub would be attached to a button addressed to the category Family "B". For each particular category, another button with a similar sub.

    It seems simple and clean to me, but do you see any issues

    As always, I value your input.


  • Jero

    SJ~

    The idea is that I am writing a program with several parameters (employees, supervisors, clients, cost ratios, etc). Each of these parameters are susceptible to change. Rather than filling a ListBox with each employee’s name, thereby making it “hard coded” into the program, I want the program to fill all of it’s variables, listboxes, and the like, from a text file that any user could easily change or add to.

    So, I have made one text file that has each category, and everything that belongs to that category, listed top to bottom. The reason for start markers and end markers (on each category) is so that the program knows where to look for that information.

    [Start family:A]
    Mike
    Jim
    Tom
    Jean
    [End family:A]

    [Start family:B]
    Steve
    Dave
    Ted
    Bob
    [End family:B]

    Does that make sense Or, does it answer your question Were you thinking of another way

    Mike


  • Nurax

    Hi Spotty…Thanks for responding.

    You’re suggestion looks good, I’m going to give it a try.

    What I have been goofing around with (unsuccessfully) is to split the ReadToEnd result into a string Array and try to loop through it until I find the two desired (starting and stopping) points. Somehow decipher which index numbers from an (unknown sized) array these two points are and have each index number’s string equivalent populate a list box.

    I made my array:

    --------------

    Dim strStringArray() As String = TextBox1.Text.Split()

    ---------

    (TextBox1.Text being the result of the ReadToEnd command given to the StreamReader.)

    I can now have a msgbox display any of the string members of the array, but to be effective, I need to figure out (in a looping statement) which index numbers the two desired points are ([start:A],[end:A])

    Other than the fact that I can’t figure out how to write the proper code to fit my design idea, do you think it has any merit

    Appreciate your input

  • Tonychen

    So the following code will work with a file format like the following

    [Start family:A]
    Tom
    Mike
    Jim
    Jean
    [End family:A]

    [Start family:B]
    Bob
    Dave
    Ted
    Steve
    [End family:B]

    Imports System.IO

    Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim objFS As FileStream
    Dim objSR As StreamReader
    Dim TextSays As String


    Dim StrFamily As String = Me.TxtFamily.Text
    If StrFamily.Length > 0 Then
    Dim StartString As String = "[Start family:" & StrFamily & "]"
    Dim EndString As String = "[End family:" & StrFamily & "]"
    Dim blnInFamily As Boolean = False

    Me.ListBox1.Items.Clear()

    Try
    objFS = New FileStream("C:\test1.txt", FileMode.Open, FileAccess.Read)
    objSR = New StreamReader(objFS)

    Do While Not objSR.EndOfStream
    TextSays = objSR.ReadLine
    If TextSays = StartString Then '//Found Start Tag
    blnInFamily = True
    ElseIf TextSays = EndString Then '//Found End Tag
    blnInFamily = False
    Else
    If blnInFamily = True Then '//In Tag Boundaries so add each line to the listbox items
    Me.ListBox1.Items.Add(TextSays)
    End If
    End If
    Loop
    objFS.Close()
    Catch ex As Exception
    MsgBox(ex.Message)
    End Try
    End If

    End Sub
    End Class

    It will pick up the family name from the textbox and populate a listbox with all the lines of peoples names in that tag.

    I'm sure there are even easier ways if you want to go down the XML route and change the file format to XML but this way is a simple parser for a simple ASCII file, which was what you were asking.


  • ACSM99

     

     

    Ohhhh, I see what you're talking about...Not 'why are there markers',  but do you need one on both ends.

    Interesting...Of course, your both right programatically, I'll just have to think about whether it has an effect on my "user friendly" design of the txt file. Thanks for clarifying that, ReneeC.

     

    Mike


  • Peter L

    Just throwing a thought out there, why not completely remove the end marker why do you need it



  • Mark Hopkins - MSFT

    Spotty~

    Thanks for the further thought...

    I'll have to ponder the issues and pick a route. Thanks again.

    Mike


  • StreamReader