VB.net split function with substring - vb.net

I want to read a certain value in a string. each line is a new string and I want to read the 6th integer on each line..
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles browsebtn.Click
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim filename As String = OpenFileDialog1.FileName
Dim streamreader As New System.IO.StreamReader(filename)
Dim textfile As String = streamreader.ReadToEnd
Dim splitChar As String = vbNewLine
Dim day As Integer = textfile.Substring(10, 2)
Dim strLine() As String = day.Split(splitChar)
For Each line As String In strLine
MsgBox(day)
Next
End If
End Sub
End Class
But it only returns one number. If I set day as a string and not an integer it works perfect, except it reads the whole string, not the two integers that I need. Please help. What am I doing wrong?
EDIT:
The input file looks like this:
23728 121010 00004986 00 00 2 21 22 11 447 114 2 382 292 350
23730 121010 00064120 00 00 51 19 21 12 1064 110 2 4500 572 7734
I want my output to be:
10
10
10 comes from "121010"

All of that code that you wrote could be done in much fewer lines, like this:
For Each line As String In File.ReadAllLines(fileName)
MessageBox.Show(line)
Next
Like your example, though, that loads the entire file into memory all at once, which could be problematic if it's a large file. If the size of the file is a concern, it would be better to just read one line at a time, like this:
Dim streamReader As New StreamReader(fileName)
Dim line As String = Nothing
Do
line = streamReader.ReadLine()
MessageBox.Show(line)
Loop Until line Is Nothing
However, the problem still remains, how do you split the line up into its individual values. If, as it appears in your question, the values are separated by spaces, then you can just use line.Split to separate the line into an array of all of its values. Then to get the last two characters of one of those values, you can just use String.SubString, like this:
Dim streamReader As New StreamReader(fileName)
Dim line As String = Nothing
Do
line = streamReader.ReadLine()
Dim parts() As String = line.Split()
Dim wholeNumber As String = parts(1)
Dim lastTwo As String = wholeNumber.SubString(wholeNumber.Length - 2)
MessageBox.Show(lastTwo)
Loop Until line Is Nothing

Some advice:
always dispose resources (use using or try catch finally with
resource.close)
never trust user inputs.
write codes that can handle enough undesired situations
Corrections based on your code:
Try
Dim text As String = Nothing
Using streamreader As New System.IO.StreamReader("text.txt")
text = streamreader.ReadToEnd()
End Using
If IsNothing(text) = False Then
Dim strLine() As String = text.Split(New String() {Environment.NewLine}, StringSplitOptions.None)
For Each line As String In strLine
If line.Length > 12 Then MsgBox(line.Substring(10, 2))
Next
End If
Catch ex As Exception
'filenotfound case
End Try
Another way:
On cases where line input can be different (but second should be looked value in our case)
Then can use Regex
Here is how:
Try
Using streamreader As New System.IO.StreamReader(file)
Dim line As String
While streamreader.Peek > 0
'unreaded line from file
line = streamreader.ReadLine()
'split input by non digits
Dim numberstrs As String() = Regex.Split(line, "\D+")
'second numbers last two
If numberstrs.Length > 1 AndAlso numberstrs(1).Length > 2 Then
Console.WriteLine("{0}", numberstrs(1).Substring(numberstrs(1).Length - 2, 2))
End If
End While
End Using
Catch ex As Exception
End Try

Steven's answer gets you most of the way there but not all the way. It's worth noting that you actually don't want the 6th integer because that could be 1 or 2 or pretty much anything depending on how you slice it. Also, given in your example you say you want to get 10 from 121010, that could be wither the second group of two numbers or the third group of two numbers from that section of the string.
I note that in your example strings you have some double spaces: You need to sort that out for a kickoff otherwise using String.Split will give you empty elements in the array. In fact, using parts(5) as Steven has used above gives you an empty element thanks to the double space, and that's not what you want anyway. You would want parts(2) and then you would need to SubString that to get the number you want.
Another, and I think more elegant, way to do it is to use a RegEx to get the number. Let's say you want the second 10 in that string (shown in bold): 12*10*10. If you know that that string will always be 6 characters, will always be the second field in the input line and you always want the third and fourth numbers then this would do you:
Imports System.Text.RegularExpressions
Imports System.IO
Private Sub ReadFile
Dim rx As New Regex("^[^\s]+\s{1}\d{2}(\d{2}?)", RegexOptions.Compiled Or RegexOptions.CultureInvariant)
Dim streamReader As New StreamReader(fileName)
Dim line As String = String.Empty
Do While streamReader.Peek >= 0
line = streamReader.ReadLine()
MessageBox.Show(rx.Matches(line)(0).Groups(1).Value)
Loop
End Sub
I'm not saying that's the only (or most elegant) RegEx but it will work and means you don't have to use SubString and it doesn't care how long the first field is. It also assumes a single space between fields but that can also be changed to suit. So long as you can work out a rule to get to the bit you want, you can RegEx it. Use Expresso (free and very powerful utility) to help you construct a suitable expression.

Related

Is it possible to use String.Split() when NewLine is the delimiter?

I have a question which asks me to calculate something from an input file. The problem is, the lines in the file don't use any special character as delimiter, like , or |. I will show it down below.
Data Communication
20
Visual Basic
40
The output I need to write to another file should look like this:
Data communication 20
Visual Basic 40
Total Books : 60
The problem is, how can I specify the delimiter? Like when there is a symbol as in strArray = strLine.Split(","). Since there is nothing I can use as delimiter, how can I split the file content?
There's no real need to split the text in the input file, when you can read a file line by line using standard methods.
You can use, e.g., a StreamReader to read the lines from the source file, check whether the current line is just text or it can be converted to a number, using Integer.TryParse and excluding empty lines.
Here, when the line read is not numeric, it's added as a Key in a Dictionary(Of String, Integer), unless it already exists (to handle duplicate categories in the source file).
If the line represents a number, it's added to the Value corresponding to the category Key previously read, stored in a variable named previousLine.
This setup can handle initial empty lines, empty lines in the text body and duplicate categories, e.g.,
Data Communication
20
Visual Basic
40
C#
100
Visual Basic
10
Other stuff
2
C++
10000
Other stuff
1
If a number is instead found in the first line, it's treated as a category.
Add any other check to handle a different structure of the input file.
Imports System.IO
Imports System.Linq
Dim basePath = "[Path where the input file is stored]"
Dim booksDict = New Dictionary(Of String, Integer)
Dim currentValue As Integer = 0
Dim previousLine As String = String.Empty
Using sr As New StreamReader(Path.Combine(basePath, "Books.txt"))
While sr.Peek > -1
Dim line = sr.ReadLine().Trim()
If Not String.IsNullOrEmpty(line) Then
If Integer.TryParse(line, currentValue) AndAlso (Not String.IsNullOrEmpty(previousLine)) Then
booksDict(previousLine) += currentValue
Else
If Not booksDict.ContainsKey(line) Then
booksDict.Add(line, 0)
End If
End If
End If
previousLine = line
End While
End Using
Now, you have a Dictionary where the Keys represent categories and the related Value is the sum of all books in that category.
You can Select() each KeyValuePair of the Dictionary and transform it into a string that represents the Key and its Value (Category:Number).
Here, also OrderBy() is used, to order the categories alphabetically, in ascending order; it may be useful.
File.WriteAllLines is then called to store the strings generated.
In the end, a new string is appended to the file, using File.AppendAllText, to write the sum of all books in all categories. The Sum() method sums all the Values in the Dictionary.
Dim newFilePath = Path.Combine(basePath, "BooksNew.txt")
File.WriteAllLines(newFilePath, booksDict.
Select(Function(kvp) $"{kvp.Key}:{kvp.Value}").OrderBy(Function(s) s))
File.AppendAllText(newFilePath, vbCrLf & "Total Books: " & booksDict.Sum(Function(kvp) kvp.Value).ToString())
The output is:
C#:100
C++:10000
Data Communication:20
Other stuff:3
Visual Basic:50
Total Books: 10173
Sure.. System.IO.File.ReadAllLines() will read the whole file and split into an array based on newlines, so you'll get an array of 4 elements. You can process it with a flipflop boolean to get alternate lines, or you can try and parse the line to a number and if it works, then its a number and if not, it's a string. If it's a number take the string you remembered (using a variable) from the previous loop
Dim arr = File.ReadALlLines(...)
Dim isStr = True
Dim prevString = ""
For Each s as String in arr
If isStr Then
prevString = s
Else
Console.WriteLine($"The string is {prevString} and the number is {s}")
End If
'flip the boolean
isStr = Not isStr
Next s
I used File.ReadAllLines to get an array containing each line in the file. Since the size of the file could be larger than the sample shown, I am using a StringBuilder. This save having to throw away and create a new string on each iteration of the loop.
I am using interpolated strings indicated by the $ preceding the quotes. This allows you to insert variables into the string surrounded by braces.
Note the Step 2 in the For loop. i will increment by 2 instead of the default 1.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lines = File.ReadAllLines("input.txt")
Dim sb As New StringBuilder
Dim total As Integer
For i = 0 To lines.Length - 2 Step 2
sb.AppendLine($"{lines(i)} {lines(i + 1)}")
total += CInt(lines(i + 1))
Next
sb.AppendLine($"Total Books: {total}")
TextBox1.Text = sb.ToString
End Sub

Reading from text files in Visual Basic

This is the first challenge on Day 1 of the 2018 Advent of Code
(link: https://adventofcode.com/2018/day/1)
So I am trying to create a program that reads a long list of positive and negative numbers (e.g +1, -2, +3, etc.) and then add them up to create a total. I have researched some methods of file handling in Visual Basic, and have come up with the below method:
Sub Main()
Dim objStreamReader As StreamReader
Dim strLine As String = ""
Dim total As Double = 0
objStreamReader = New StreamReader(AppDomain.CurrentDomain.BaseDirectory & "frequencies.txt")
strLine = objStreamReader.ReadLine
Do While Not strLine Is Nothing
Console.WriteLine(strLine)
strLine = objStreamReader.ReadLine
total += strLine
Loop
Console.WriteLine(total)
objStreamReader.Close()
Console.ReadLine()
End Sub
Here is a link to the list of numbers: https://adventofcode.com/2018/day/1/input
It is not a syntax error I am getting but a logic error. The answer is somehow wrong, but I cannot seem to figure out where! I have tried to remove the signs from each number but that throws me a NullException error when it compiles.
So far I have come out with the answer 549, which the Advent of Code webiste rejects. Any ideas?
Make your life easier by using File.ReadLines(fileName) instead of dealing with StreamReader. Use Path.Combine instead of string concatenation to create a path. Path.Combine takes care of adding missing \ or removing extra ones etc.
Your file might contain an extra empty line at its end, that does not convert to a number. Use Double.TryParse to make sure you have a valid number before totalizing it. You should have Option Strict On anyway to enforce explicit conversions.
Dim fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "frequencies.txt")
Dim total As Double = 0
For Each strLine As String In File.ReadLines(fileName)
Console.WriteLine(strLine)
Dim n As Double
If Double.TryParse(strLine, n) Then
total += n
End If
Next
Console.WriteLine(total)
Console.ReadLine()
For appending two string, please use string builder.
Dim test as new stringbuilder()
Test.append("your string")
It will not affect performance.

Extracting text from a textfile starting with one word and ending on a different line with a different word

I need to extract text from a text file starting with the order number(eg. Order1) and ending with an empty line with all other lines between the order number and the empty line extracted as well for a query. Really have no idea how to go about this so any help is greatly appreciated!
so the file name is "CustomerDetails.txt" and I'd imagine the code would look something like this
If IO.File.Exists("CustomerDetails.txt") Then
Dim inFile As IO.StreamReader = IO.File.OpenText(“CustomerDetails.txt")
End If
and then taking for example "order1" in that text file until the blank space and displaying that is a list box
"Really have no idea how to go about this "
The thinking could go like this...
A text file has a string in it.
I could look up the String class in .net and see if there are any methods that could help me.
Search for "String class in .net"
Looks like we can use a combination of String.IndexOf(String, Int32) and String.Substring(Int32, Int32)
Find the IndexOf your order. The string will be the order "Order1" and we will start looking at index 0 so the Int32 will be 0. Then find the end index. Start looking at the index we just found and stop at the first blank line. We can get the length required by the `.Substring method by subtracting the start index from the end index. Now we can extract the text of Order 1 with the substring method.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim OrderText As String = "Order 1" 'this could be set with TextBox1.Text
'Get the string out of the file
Dim s As String = File.ReadAllText("CustomerDetails.txt")
'Find the index of the order, this overload assumes start index is 0
Dim startIndex As Integer = s.IndexOf(OrderText) 'starts lookint at beginning
'Find the index of the first blank line after the startIndex
'2 new lines make a bland line
Dim endIndex As Integer = s.IndexOf(Environment.NewLine & Environment.NewLine, startIndex)
'Return the string that stars at startIndex with a length of end minus start
Dim Order As String = s.Substring(startIndex, endIndex - startIndex)
'I am going to guess that the details of the order are on separate lines
Dim lines() As String = Order.Split(New String() {Environment.NewLine}, StringSplitOptions.None)
For Each line As String In lines
ListBox1.Items.Add(line)
Next
End Sub

VB.NET: How to find a word after a specific word in a line and store it

I have a continuous string of words coming from a machine to hyper terminal of my system, for which I am using USB to serial cable. I want to find some of the values which comes after a specific word in that string and then store it.
I used threads and splitting concepts to do it but as per the requirement and operation of the machine it will not work properly in the runtime.
The values which I want to capture comes from a specific word. I want to skip that words and just store the values. How to do it?
I have given the example of that string below:
MEAN 49 50
SD 500 10
MIN 100 5
MAX 50 45.56
In this I just want to store the values e.g. 49 and 50, then discard MEAN. Then discard SD and store 500 and 10 and so on.
You can use a StreamReader object to read the stream one line at a time. Then, you can easily parse the line using the String.Split method. I would recommend creating one or more classes that represent the data being read, like this:
Public Class LineData
Public Property Label As String
Public Property Value1 As Decimal
Public Property Value2 As Decimal
End Class
Public Function ReadNextLine(stream As Stream) As LineData
Dim reader As New StreamReader(stream)
Dim line As String = reader.ReadLine()
Dim data As LineData = Nothing
If line IsNot Nothing Then
Dim words() As String = line.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries)
If words.Length = 3 Then
data = New LineData()
data.Label = words(0)
data.Value1 = Decimal.Parse(words(1))
data.Value2 = Decimal.Parse(words(2))
End If
End If
Return Data
End Function
Note, this is a very simple example based on the example data you provided. If different lines have different numbers of numeric parameters, that will further complicate the logic. In my example, the method returns Nothing if no data can be read. Also, the method will throw an exception if the last two words in the line are not numeric. Therefore, you would need to wrap it in some additional exception handling.
This may be what you're looking for. Although personally I'd create a class which stores the type(mean, median etc), firstvalue and secondvalue.
By the sounds of it though, all you want it to do is dump the values into some sort of storage, therefore this will suffice.
Dim Values as New List(Of Decimal)
'Use a streamreader to read each line of text
Using reader As StreamReader = New StreamReader(*your text source*)
'Read the line
Dim linetext as string = reader.ReadLine
Dim myValue as decimal
'Split the line
Dim splitText() = linetext.Split(" ")
'Analyze each section of the line, if its possible to parse the value as a decimal then add it to the list of values to be stored.
For Each txt in splitText
If Decimal.TryParse(txt, myValue) then Values.Add(myValue)
Next
End Using

Visual Basic Read File Line by Line storing each Line in str

I am trying to loop through the contents of a text file reading the text file line by line. During the looping process there is several times I need to use the files contents.
Dim xRead As System.IO.StreamReader
xRead = File.OpenText(TextBox3.Text)
Do Until xRead.EndOfStream
Dim linetext As String = xRead.ReadLine
Dim aryTextFile() As String = linetext.Split(" ")
Dim firstname As String = Val(aryTextFile(0))
TextBox1.Text = firstname.ToString
Dim lastname As String = Val(aryTextFile(0))
TextBox2.Text = lastname.ToString
Loop
Edit: What I am trying to do is read say the first five items in a text file perform some random processing then read the next 5 lines of the text file.
I would like to be able to use the lines pulled from the text file as separated string variables.
It is not clear why you would need to have 5 lines stored at any time, according to your code sample, since you are only processing one line at a time. If you think that doing 5 lines at once will be faster - this is unlikely, because .NET maintains caching internally, so both approaches will probably perform the same. However, reading one line at a time is a much more simple pattern to use, so better look into that first.
Still, here is an approximate version of the code that does processing every 5 lines:
Sub Main()
Dim bufferMaxSize As Integer = 5
Using xRead As New System.IO.StreamReader(TextBox3.Text)
Dim buffer As New List(Of String)
Do Until xRead.EndOfStream
If buffer.Count < bufferMaxSize Then
buffer.Add(xRead.ReadLine)
Continue Do
Else
PerformProcessing(buffer)
buffer.Clear()
End If
Loop
If buffer.Count > 0 Then
'if line count is not divisible by bufferMaxSize, 5 in this case
'there will be a remainder of 1-4 records,
'which also needs to be processed
PerformProcessing(buffer)
End If
End Using
End Sub
Here is mine . Rely easy . Just copy the location from the file and copy1 folder to does locations . This is my first program :) . ready proud of it
Imports System.IO
Module Module1
Sub Main()
For Each Line In File.ReadLines("C:\location.txt".ToArray)
My.Computer.FileSystem.CopyDirectory("C:\Copy1", Line, True)
Next
Console.WriteLine("Done")
Console.ReadLine()
End Sub
End Module