VB.NET 与文本文件相关的索引超出范围异常
VB.NET Index out of Range exception related to text file
我有一些代码我用了很多次,对我来说一直很管用。然而,最新的使用在某些我似乎无法解决的情况下抛出异常。这是:
我从一个文本文件读取到一个数组,将它用作我的一些控件的绑定源(它根据单个控件的选择自动填充 3 个控件)。我创建了一个具有 4 个属性(名称、ID、DOB 和 DOE)的 Student class。这是我使用的代码:
Private Sub autoFill()
Dim rost As String = "Roster.txt"
Dim lines As List(Of String) = File.ReadAllLines(rost).ToList
Dim list As List(Of Student) = New List(Of Student)
For i As Integer = 0 To lines.Count - 1
Dim data As String() = lines(i).Split(":")
list.Add(New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
})
Next
StudentBindingSource.DataSource = list
End Sub
问题来了。在“For”循环中,当我将 i 设置为 0 到 lines.count -1 时,它会抛出此错误:
VB>NET EXCEPTION
但是...如果我将 i 更改为 1 而不是 0 它会起作用,或者如果我拿走 data(2) 和 data(3) 它会在 i = 0 时起作用。我宁愿使用 0 这样我可以在组合框中有一个空行或“--选择--”等。我认为唯一可能有用的是文本文件中的第一行没有要拆分的内容。这是文本文件的行格式:
Student Name ID# DOB DOE <-----This header row is NOT in the text file
Last Name, First Name : 0000000 : 01/01/2021 : 01/01/2021
我假设我在这里遗漏了一些非常简单的东西。任何指导将不胜感激!谢谢。
在解决实际问题之前,让我们重新做一些事情。
一种更好的结构代码方法,尤其是在处理数据加载时,是使用一种接受输入并 returns 结果的方法。此外,调用 ToList()
或 ToArray()
是一项 非常昂贵 的性能操作。通常,您可以通过尽可能长时间地使用较低级别 IEnumerable
来显着 提高性能。
考虑到这些原则,请考虑以下代码:
Private Function ReadStudentData(fileName As String) As IEnumerable(Of Student)
Dim lines As IEnumerable(Of String) = File.ReadLines(fileName)
Return lines.
Select(Function(line) line.Split(":")).
Select(Function(data)
Return New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
}
End Function)
End Function
Private Sub autoFill()
StudentBindingSource.DataSource = ReadStudentData("Roster.txt")
End Sub
现在进入实际问题。问题是 而不是 循环遍历 list
变量。问题是 data
数组。在某些时候,您的一行没有足够的元素。这很常见,例如,作为文件中的最后一行。
有许多 方法可以解决这个问题。在某些情况下,异常已经是合适的结果,因为如果你有坏数据,你真的不想继续。在其他情况下,您希望记录错误记录,也许是一份您以后可以轻松查看的报告。或者您可能只想忽略该错误,或预过滤具有正确列数的行。这是最后一个选项的示例:
Private Function ReadStudentData(fileName As String) As IEnumerable(Of Student)
Return File.ReadLines(fileName).
Select(Function(line) line.Split(":")).
Where(Function(data) data.Length = 4).
Select(Function(data)
Return New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
}
End Function)
End Function
Private Sub autoFill()
StudentBindingSource.DataSource = ReadStudentData("Roster.txt")
End Sub
问题是您没有检查 'data' 是否有足够的元素来创建 'Student'。一个简单的检查应该可以解决它。
Private Sub autoFill()
Dim rost As String = "Roster.txt"
Dim lines As List(Of String) = File.ReadAllLines(rost).ToList
Dim list As List(Of Student) = New List(Of Student)
For i As Integer = 0 To lines.Count - 1
Dim data As String() = lines(i).Split(":"c)
'Check data
If data.Length >= 4 Then '
list.Add(New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
})
End If
Next
StudentBindingSource.DataSource = list
End Sub
试试这个代码:
Dim list As List(Of Student) = New List(Of Student)(100)
基本上用一个容量初始化学生列表。这是列表的容量,不是count/length.
我有一些代码我用了很多次,对我来说一直很管用。然而,最新的使用在某些我似乎无法解决的情况下抛出异常。这是:
我从一个文本文件读取到一个数组,将它用作我的一些控件的绑定源(它根据单个控件的选择自动填充 3 个控件)。我创建了一个具有 4 个属性(名称、ID、DOB 和 DOE)的 Student class。这是我使用的代码:
Private Sub autoFill()
Dim rost As String = "Roster.txt"
Dim lines As List(Of String) = File.ReadAllLines(rost).ToList
Dim list As List(Of Student) = New List(Of Student)
For i As Integer = 0 To lines.Count - 1
Dim data As String() = lines(i).Split(":")
list.Add(New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
})
Next
StudentBindingSource.DataSource = list
End Sub
问题来了。在“For”循环中,当我将 i 设置为 0 到 lines.count -1 时,它会抛出此错误:
VB>NET EXCEPTION
但是...如果我将 i 更改为 1 而不是 0 它会起作用,或者如果我拿走 data(2) 和 data(3) 它会在 i = 0 时起作用。我宁愿使用 0 这样我可以在组合框中有一个空行或“--选择--”等。我认为唯一可能有用的是文本文件中的第一行没有要拆分的内容。这是文本文件的行格式:
Student Name ID# DOB DOE <-----This header row is NOT in the text file
Last Name, First Name : 0000000 : 01/01/2021 : 01/01/2021
我假设我在这里遗漏了一些非常简单的东西。任何指导将不胜感激!谢谢。
在解决实际问题之前,让我们重新做一些事情。
一种更好的结构代码方法,尤其是在处理数据加载时,是使用一种接受输入并 returns 结果的方法。此外,调用 ToList()
或 ToArray()
是一项 非常昂贵 的性能操作。通常,您可以通过尽可能长时间地使用较低级别 IEnumerable
来显着 提高性能。
考虑到这些原则,请考虑以下代码:
Private Function ReadStudentData(fileName As String) As IEnumerable(Of Student)
Dim lines As IEnumerable(Of String) = File.ReadLines(fileName)
Return lines.
Select(Function(line) line.Split(":")).
Select(Function(data)
Return New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
}
End Function)
End Function
Private Sub autoFill()
StudentBindingSource.DataSource = ReadStudentData("Roster.txt")
End Sub
现在进入实际问题。问题是 而不是 循环遍历 list
变量。问题是 data
数组。在某些时候,您的一行没有足够的元素。这很常见,例如,作为文件中的最后一行。
有许多 方法可以解决这个问题。在某些情况下,异常已经是合适的结果,因为如果你有坏数据,你真的不想继续。在其他情况下,您希望记录错误记录,也许是一份您以后可以轻松查看的报告。或者您可能只想忽略该错误,或预过滤具有正确列数的行。这是最后一个选项的示例:
Private Function ReadStudentData(fileName As String) As IEnumerable(Of Student)
Return File.ReadLines(fileName).
Select(Function(line) line.Split(":")).
Where(Function(data) data.Length = 4).
Select(Function(data)
Return New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
}
End Function)
End Function
Private Sub autoFill()
StudentBindingSource.DataSource = ReadStudentData("Roster.txt")
End Sub
问题是您没有检查 'data' 是否有足够的元素来创建 'Student'。一个简单的检查应该可以解决它。
Private Sub autoFill()
Dim rost As String = "Roster.txt"
Dim lines As List(Of String) = File.ReadAllLines(rost).ToList
Dim list As List(Of Student) = New List(Of Student)
For i As Integer = 0 To lines.Count - 1
Dim data As String() = lines(i).Split(":"c)
'Check data
If data.Length >= 4 Then '
list.Add(New Student() With {
.StudentName = data(0),
.StudentID = data(1),
.StudentDOB = data(2),
.StudentDOE = data(3)
})
End If
Next
StudentBindingSource.DataSource = list
End Sub
试试这个代码:
Dim list As List(Of Student) = New List(Of Student)(100)
基本上用一个容量初始化学生列表。这是列表的容量,不是count/length.