StreamReader - Reading from lines - vb.net

I have the following code;
Public Sub writetofile()
' 1: Append playername
Using writer As StreamWriter = New StreamWriter("highscores.txt", True)
writer.WriteLine(PlayerName)
End Using
' 2: Append score
Using writer As StreamWriter = New StreamWriter("highscores.txt", True)
writer.WriteLine(Score)
End Using
End Sub
What I now want to do is read all the odd lines of the file (the player names) and the even lines into two separate list boxes, how would I go about that??
I need to modify;
Using reader As StreamReader = New StreamReader("file.txt")
' Read one line from file
line = reader.ReadLine
End Using
I have used one of the following solutions but cannot get it working :(
Public Sub readfromfile()
Using reader As New StreamReader("scores.txt", True)
Dim line As Integer = 0
While Not reader.EndOfStream
If line Mod 2 = 0 Then
frmHighScores.lstScore.Items.Add(line)
Else
frmHighScores.lstScore.Items.Add(line)
End If
line += 1
End While
End Using
End Sub

You can use the Mod operator for this:
Using reader As New StreamReader("highscores.txt", True)
Dim line As Integer = 0
Dim text As String
Do
text = reader.ReadLine()
If text = Nothing Then
Exit Do
End If
If line Mod 2 = 0 Then
''# even line
Else
''# odd line
End If
line += 1
Loop
End Using
This approach also works for cases when it's not an even/odd pattern, but another number of repetions. Say you have 3 lines for each player:
player name 1
score 1
avatar url 1
player name 2
score 2
avatar url 2
...
Then you can get this pattern by using Mod with 3
Dim subLine As Integer = line Mod 3
If subLine = 0 Then
''# player name
ElseIf subLine = 1 Then
''# score
Else
''# avatar url
End If
line += 1

If you can reliably expect there to be an even number of lines in the file, then you can simplify this by reading two at a time.
Using reader As StreamReader = New StreamReader("file.txt")
While Not reader.EndOfStream
Dim player as String = reader.ReadLine()
Dim otherInfo as String = reader.ReadLine()
'Do whatever you like with player and otherInfo
End While
End Using

I don't really know the syntax of VB but something like this:
dim odd as boolean = True
Using reader As StreamReader = New StreamReader("file.txt")
line = reader.ReadLine
if odd then
' add to list A
else
' add to list B
end
odd = Not Odd
End Using

Another possibility is to just read the whole file as a block into a single string and the SPLIT the string on vbcrlf
Dim buf = My.Computer.FileSystem.ReadAllText(Filename)
Dim Lines() = Split(Buf, vbcrlf)
Then, lines will contain all the lines from the file, indexed.
So you could step through them to get each player and his other info.
For x = 0 to ubound(Lines)
'do whatever with each line
next
If the file was HUGE, you wouldn't necessarily want to do it this way, but for small files, it's a quick and easy way to handle it.

Related

Through lines textbox startwith and endswith something

in my File Text I have the following things:
I have to make it start from somewhere and stop at a certain point.
but he only starts from that point, but he does not know how to stop at one point.
[Letters]
A
B
C
D
E
[Loop]
[Words]
Fish
Facebook
Google
Youtube
I should display Expected Output:
A
B
C
D
E
Then I should make it display
Fish
Facebook
Google
Youtube
but it shows me:
[Letters]
A
B
C
D
E
[Loop]
[Words]
Fish
Facebook
Google
Youtube
Code
Dim line As String
Using reader As StreamReader = New StreamReader(My.Application.Info.DirectoryPath & "\TestReader.txt")
line = reader.ReadLine
Dim sb As New StringBuilder
Do
Do
If reader.Peek < 0 Then 'Check that you haven't reached the end
Exit Do
End If
line = reader.ReadLine
If line.StartsWith("[Letters]") AndAlso line.EndsWith("[Loop]") Then 'Check if we have reached another check box.
Exit Do
End If
sb.AppendLine(line)
Loop
TextBox1.Text = sb.ToString
sb.Clear()
Loop Until reader.Peek < 0
End Using
This assumes that startPrefix and endPrefix will always be present in the file:
Dim startPrefix As String 'Set as required
Dim endPrefix As String 'Set as required
Dim lines As New List(Of String)
Using reader As New StreamReader("file path here")
Dim line As String
'Skip lines up to the first starting with the specified prefix.
Do
line = reader.ReadLine()
Loop Until line.StartsWith(startPrefix)
line = reader.ReadLine()
Do Until line.StartsWith(endPrefix)
lines.Add(line)
line = reader.ReadLine()
Loop
End Using
'Use lines here.
Are you really sure that you want to look for lines that start with those markers though? Wouldn't you really prefer to look for lines that are equal to those markers?
EDIT:
You could - and probably should - encapsulate that functionality in a method:
Private Function GetLinesBetween(filePath As String, startPrefix As String, endPrefix As String) As String()
Dim lines As New List(Of String)
Using reader As New StreamReader(filePath)
Dim line As String
'Skip lines up to the first starting with the specified prefix.
Do
line = reader.ReadLine()
Loop Until line.StartsWith(startPrefix)
line = reader.ReadLine()
'Take lines up to the first starting with the specified prefix.
Do Until line.StartsWith(endPrefix)
lines.Add(line)
line = reader.ReadLine()
Loop
End Using
Return lines.ToArray()
End Function

Creating multiple .txt files while restricting size of each

In my program, I collect bits of information on a massive scale, hundreds of thousands to millions of lines each. I am trying to limit each file I create to a certain size in order to be able to quickly open it and read the data. I am using a HashSet to collect all the data without duplicates.
Here's my code so far:
Dim Founds As HashSet(Of String)
Dim filename As String = (Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\Sorted_byKING\sorted" + Label4.Text + ".txt")
Using writer As New System.IO.StreamWriter(filename)
For Each line As String In Founds
writer.WriteLine(line)
Next
Label4.Text = Label4.Text + 1 'Increments sorted1.txt, sorted2.txt etc
End Using
So, my question is:
How do I go about saving, let's say 250,000 lines in a text file before moving to another one and adding the next 250,000?
First of all, do not use Labels to simply store values. You should use variables instead, that's what variables are for.
Another advice, always use Path.Combine to concatenate paths, that way you don't have to worry about if each part of the path ends with a separator character or not.
Now, to answer your question:
If you'd like to insert the text line by line, you can use something like:
Sub SplitAndWriteLineByLine()
Dim Founds As HashSet(Of String) 'Don't forget to initialize and fill your HashSet
Dim maxLinesPerFile As Integer = 250000
Dim fileNum As Integer = 0
Dim counter As Integer = 0
Dim filename As String = String.Empty
Dim writer As IO.StreamWriter = Nothing
For Each line As String In Founds
If counter Mod maxLinesPerFile = 0 Then
fileNum += 1
filename = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
$"Sorted_byKING\sorted{fileNum.ToString}.txt")
If writer IsNot Nothing Then writer.Close()
writer = New IO.StreamWriter(filename)
End If
writer.WriteLine(line)
counter += 1
Next
writer.Dispose()
End Sub
However, if you will be inserting the text from the HashSet as is, you probably don't need to write line by line, instead you can write each "bunch" of lines at once. You could use something like the following:
Sub SplitAndWriteAll()
Dim Founds As HashSet(Of String) 'Don't forget to initialize and fill your HashSet
Dim maxLinesPerFile As Integer = 250000
Dim fileNum As Integer = 0
Dim filename As String = String.Empty
For i = 0 To Founds.Count - 1 Step maxLinesPerFile
fileNum += 1
filename = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
$"Sorted_byKING\sorted{fileNum.ToString}.txt")
IO.File.WriteAllLines(filename, Founds.Skip(i).Take(maxLinesPerFile))
Next
End Sub

VB "Index was out of range, must be non-negative and less than the size of the collection." When trying to generate a random number more than once

So I'm trying to generate a random number on button click. Now this number needs to be between two numbers that are inside my text file with various other things all separated by the "|" symbol. The number is then put into the text of a textbox which is being created after i run the form. I can get everything to work perfectly once, but as soon as i try to generate a different random number it gives me the error: "Index was out of range, must be non-negative and less than the size of the collection." Here is the main code as well as the block that generates the textbox after loading the form. As well as the contents of my text file.
Private Sub generate()
Dim newrandom As New Random
Try
Using sr As New StreamReader(itemfile) 'Create a stream reader object for the file
'While we have lines to read in
Do Until sr.EndOfStream
Dim line As String
line = sr.ReadLine() 'Read a line out one at a time
Dim tmp()
tmp = Split(line, "|")
rows(lineNum).buybutton.Text = tmp(1)
rows(lineNum).buyprice.Text = newrandom.Next(tmp(2), tmp(3)) 'Generate the random number between two values
rows(lineNum).amount.Text = tmp(4)
rows(lineNum).sellprice.Text = tmp(5)
rows(lineNum).sellbutton.Text = tmp(1)
lineNum += 1
If sr.EndOfStream = True Then
sr.Close()
End If
Loop
End Using
Catch x As Exception ' Report any errors in reading the line of code
Dim errMsg As String = "Problems: " & x.Message
MsgBox(errMsg)
End Try
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
rows = New List(Of duplicate)
For dupnum = 0 To 11
'There are about 5 more of these above this one but they all have set values, this is the only troublesome one
Dim buyprice As System.Windows.Forms.TextBox
buyprice = New System.Windows.Forms.TextBox
buyprice.Width = textbox1.Width
buyprice.Height = textbox1.Height
buyprice.Left = textbox1.Left
buyprice.Top = textbox1.Top + 30 * dupnum
buyprice.Name = "buypricetxt" + Str(dupnum)
Me.Controls.Add(buyprice)
pair = New itemrow
pair.sellbutton = sellbutton
pair.amount = amounttxt
pair.sellprice = sellpricetxt
pair.buybutton = buybutton
pair.buyprice = buypricetxt
rows.Add(pair)
next
end sub
'textfile contents
0|Iron Sword|10|30|0|0
1|Steel Sword|20|40|0|0
2|Iron Shield|15|35|0|0
3|Steel Shield|30|50|0|0
4|Bread|5|10|0|0
5|Cloak|15|30|0|0
6|Tent|40|80|0|0
7|Leather Armour|50|70|0|0
8|Horse|100|200|0|0
9|Saddle|50|75|0|0
10|Opium|200|500|0|0
11|House|1000|5000|0|0
Not sure what else to add, if you know whats wrong please help :/ thanks
Add the following two lines to the start of generate():
Private Sub generate()
Dim lineNum
lineNum = 0
This ensures that you don't point to a value of lineNum outside of the collection.
I usually consider it a good idea to add
Option Explicit
to my code - it forces me to declare my variables, and then I think about their initialization more carefully. It helps me consider their scope, too.
Try this little modification.
I took your original Sub and changed a little bit take a try and let us know if it solve the issue
Private Sub generate()
Dim line As String
Dim lineNum As Integer = 0
Dim rn As New Random(Now.Millisecond)
Try
Using sr As New StreamReader(_path) 'Create a stream reader object for the file
'While we have lines to read in
While sr.Peek > 0
line = sr.ReadLine() 'Read a line out one at a time
If Not String.IsNullOrEmpty(line) And Not String.IsNullOrWhiteSpace(line) Then
Dim tmp()
tmp = Split(line, "|")
rows(lineNum).buybutton.Text = tmp(1)
rows(lineNum).buyprice.Text = rn.Next(CInt(tmp(2)), CInt(tmp(3))) 'Generate the random number between two values
rows(lineNum).amount.Text = tmp(4)
rows(lineNum).sellprice.Text = tmp(5)
rows(lineNum).sellbutton.Text = tmp(1)
lineNum += 1
End If
End While
End Using
Catch x As Exception ' Report any errors in reading the line of code
Dim errMsg As String = "Problems: " & x.Message
MsgBox(errMsg)
End Try
End Sub

How to check if lines in string are separated by space?

I'm building a program that gets the publisher of the book by scanning its title page and using OCR … since publishers are always at the bottom of the title page I'm thinking that a detecting lines that are separated by space is a solution but I don't know how to test for that. Here is my code:
Dim builder As New StringBuilder()
Dim reader As New StringReader(txtOCR.Text)
Dim iCounter As Integer = 0
While True
Dim line As String = reader.ReadLine()
If line Is Nothing Then Exit While
'i want to put the condition here
End While
txtPublisher.Text = builder.ToString()
Do you mean empty lines? Then you can do this:
Dim bEmpty As Boolean
And then inside the loop:
If line.Trim().Length = 0 Then
bEmpty = True
Else
If bEmpty Then
'...
End If
bEmpty = False
End If
Why not do the following: from the bottom, go up until you find the first non-empty line (no idea how the OCR works … maybe the bottom-most line is always non-empty, in which case this is redundant). In the next step, go up until the first empty line. The text in the middle is the publisher.
You don’t need the StringReader for that:
Dim lines As String() = txtOCR.Text.Split(Environment.NewLine)
Dim bottom As Integer = lines.Length - 1
' Find bottom-most non-empty line.
Do While String.IsNullOrWhitespace(lines(bottom))
bottom -= 1
Loop
' Find empty line above that
Dim top As Integer = bottom - 1
Do Until String.IsNullOrWhitespace(lines(top))
top -= 1
Loop
Dim publisherSubset As New String(bottom - top)()
Array.Copy(lines, top + 1, publisherSubset, 0, bottom - top)
Dim publisher As String = String.Join(Environment.NewLine, publisherSubset)
But to be honest I don’t think this is a particularly good approach. It’s inflexible and doesn’t cope well with unexpected formatting. I’d instead use a regular expression to describe what the publisher string (and its context) looks like. And maybe even that isn’t enough and you have to put some thought into describing the whole page to extrapolate which of the bits is the publisher.
Assuming the publisher is always on the last line and always comes after an empty line. Then perhaps the following?
Dim Lines as New List(Of String)
Dim currentLine as String = ""
Dim previousLine as String = ""
Using reader As StreamReader = New StreamReader(txtOCR.Txt)
currentLine = reader.ReadLine
If String.IsNullOrWhiteSpace(previousLine) then lines.Add(currentLine)
previousLine = currentLine
End Using
txtPublisher.Text = lines.LastOrDefault()
To ignore if the previous line is blank/empty:
Dim Lines as New List(Of String)
Using reader As StreamReader = New StreamReader(txtOCR.Txt)
lines.Add(reader.ReadLine)
End Using
txtPublisher.Text = lines.LastOrDefault()

Find a specific line of text in a text document and insert the next 37 lines of text into a database

Helo,
I have an SQL database, and 50 text files, and Visual Basic 2010 Premimum,
I need to find a specific line of text in the text files and then take the next 37 lines of text and save them in my database. I need advice as to point me in the right direction. Also if anyone might know of a book I can use for future reference it would be greatly appreciated.
Const textToFind As String = "a specific line of text"
Const maxLineCount As Int32 = 37
Dim allLines As New List(Of String)
Dim path As String = "c:\temp\MyTest.txt"
Try
If File.Exists(path) Then
File.Delete(path)
End If
Dim sw As StreamWriter = New StreamWriter(path)
For i As Int32 = 1 To 100
sw.WriteLine("This")
sw.WriteLine("is some text")
sw.WriteLine("to test")
sw.WriteLine("Reading")
sw.WriteLine("a specific line of text")
Next
sw.Close()
Dim sr As StreamReader = New StreamReader(path)
Dim lineCounter As Int32 = 0
Dim lineFound As Int32 = -1
Do While sr.Peek() >= 0
Dim line As String = sr.ReadLine
If lineFound = -1 Then
If line.Equals(textToFind) Then
lineFound = 0
End If
Else
lineCounter += 1
If lineCounter <= maxLineCount Then
allLines.Add(line)
Else
Exit Do
End If
End If
Loop
sr.Close()
' save found lines to the database '
Catch ex As Exception
Console.WriteLine("The process failed: {0}", ex.ToString())
End Try
As for parsing the file, it's easy to search files line-by-line:
Var i = 0
Var foundOnLineNumber = -1
For Each line In File.ReadAllLines("<file name here>")
i = i + 1
If foundOnLineNumber > 0 Then
' Add line to database
Else If <criteria for finding "that" line> Then
foundOnLineNumber = i
End If
Next
I've never been good at VB (I usually do C#, so this might not compile). Try to figure out what criteria you are looking for and replace that in the code above. Here is a list of VB.NET books. Find one that covers ADO or some other database access technology. I think your biggest help will be to simply get a good grasp on the VB language and the facilities that .NET has at its disposal.