VB.NET - Substring Function Doesn't Work Correctly

96 Views Asked by At

I have a file in the project called this.txt. This file contains Coordinates of a drawing.

In each line in the file , there are 4 values. Between each value , There is a character separating the values.

For example : 109 n 66 m 110 a 67 b

Here, There is a character between each value.

In my program , I read the file this.txt using StreamReader.

And make a for loop on the number of lines. In this loop , Every line in the text I save it in an array. I put characters between the values to put the values in variables using Substring Function.

This Is My Code :

Imports System.IO

Public Class Form1
  Dim array2(200) As String
  Dim theLine1 As String
  Dim theLine2 As String
  Dim theLine3 As String
  Dim theLine4 As String

  Private Sub btn_Read_Click(sender As Object, e As EventArgs) Handles btn_Read.Click
      Dim sw2 As New StreamReader("this.txt")
      Dim lineCount = File.ReadAllLines("this.txt").Length
      For t = 0 To lineCount
         array2(t) = sw2.ReadLine
         theLine1 = array2(t).Substring(0, array2(t).IndexOf("n")).Trim()
         theLine2 = array2(t).Substring(array2(t).IndexOf("n") + 1, array2(t).IndexOf("m")).Trim()
         theLine3 = array2(t).Substring(array2(t).IndexOf("m") + 1, array2(t).IndexOf("a")).Trim()
         theLine4 = array2(t).Substring(array2(t).IndexOf("a") + 1, array2(t).IndexOf("b")).Trim()
      Next
  End Sub

End Class

The program read the first value corectly and put it in theLine1 Variable. But In next value , The program read the second value and the third value and put it in theLine2 Variable. Using the previous Example : 109 n 66 m 110 a 67 b

The program put 66 m 110 in the theLine2 Variable. And I don't want this and I don't know why this happen. I just want put the next value in theLine2 Variable.

And also when the program reach the theLine3 Varaible. The program show to me an error.

This is the error :

An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll

Additional information: Index and length must refer to a location within the string.

2

There are 2 best solutions below

0
Daniel On

As far as I understand, you want to extract the numbers between the letters, line by line. In your substring function, you should have specified the length as the second parameter, indicating “how much further do I need to look”. However, you still have a letter before the number. It's easier to use Split instead.

You also don't need a Stream Reader. Since you didn't use Using, you might lock the file, preventing it from being manually opened again.

I declared the variables for the numbers as integers and kept them local. If you need them globally, feel free to change it back.

I also added checks to ensure that there is always something in the respective read line.

The lines in the txt file:

205 n 92 m 308 a 110 b
76 n 201 m 44 a 89 b
312 n 57 m 102 a 123 b
219 n 68 m 150 a 81 b
Public NotInheritable Class Form1

    Private Sub btn_Read_Click(sender As Object, e As EventArgs) Handles btn_Read.Click
        Dim path As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\new 1.txt"
        If Not System.IO.File.Exists(path) Then
            Return
        End If
        Dim lines As String() = System.IO.File.ReadAllLines(path, System.Text.Encoding.UTF8)
        For i As Integer = 0 To lines.Length - 1 Step 1
            If String.IsNullOrEmpty(lines(i)) Then
                Continue For
            End If

            Dim numbers As String() = lines(i).Split({"n"c, "m"c, "b"c, "a"c, " "c}, StringSplitOptions.RemoveEmptyEntries)
            If numbers.Length < 4 Then
                Continue For
            End If
            Dim firstValue As Integer = Integer.Parse(numbers(0))
            Dim secondValue As Integer = Integer.Parse(numbers(1))
            Dim thirdValue As Integer = Integer.Parse(numbers(2))
            Dim fourthValue As Integer = Integer.Parse(numbers(3))
            Debug.WriteLine(firstValue.ToString() + " " + secondValue.ToString() + " " + thirdValue.ToString() + " " + fourthValue.ToString())
        Next
    End Sub
End Class

Result:

205 92 308 110
76 201 44 89
312 57 102 123
219 68 150 81
0
Enigmativity On

Perhaps consider using Regex. Then your code can look like this:

Dim lines = File.ReadLines("this.txt")

Dim regex = New Regex("^(?<n>\d+)\sn\s(?<m>\d+)\sm\s(?<a>\d+)\sa\s(?<b>\d+)\sb$")

Dim array2 = _
    lines _
        .[Select](Function(x) regex.Match(x)) _
        .[Select](Function(m) _
        { _
            m.Groups("n").Value, _
            m.Groups("m").Value, _
            m.Groups("a").Value, _
            m.Groups("b").Value _
        })