使用Visual Basic。尝试将一系列报告加载到列表视图时,列表视图每次加载时都会由3列(位置,日期和严重性级别)组成,由于``索引超出数组范围''而崩溃时会崩溃(尤其是在DOI = reportdetails(1)周围)在我的代码中。它正在从文本文件中加载。我在文本文件中有数据,所以我不确定为什么要说我要的信息不存在。该程序还加密文本文件。
Dim locate, DOI, SeverityLevel, ReportTitles, EReportTitles, ReportDetails(2) As String
Dim Index As Integer 'Define Variables
Dim FileNum As Integer = FreeFile()
Dim IncidentReport As ListViewItem
lstReports.Items.Clear()
If Dir("ReportTitles.txt") <> "" Then 'If the directory of the file exits then continue
FileOpen(FileNum, "ReportTitles.txt", OpenMode.Input) 'open file
Do Until EOF(FileNum) 'Repeat until the end of the file is reached
EReportTitles = "" 'Clear variables, to safeguard against crashes or errors
ReportTitles = ""
EReportTitles = LineInput(FileNum) 'EReportTitles is equal to the current file line
Dim FileName As String = "ReportTitles.txt" 'Define variables
Dim I, C As Integer
Dim Last As Integer = EReportTitles.Length - 1
Dim ThisChar As Char
For I = 0 To Last 'Begin for loop
ThisChar = EReportTitles.Chars(I) 'Decryption of file
C = Asc(ThisChar) Xor 22
ThisChar = Chr(C)
ReportTitles += ThisChar
Next
If ReportTitles <> "" Then
ReportDetails = Split(ReportTitles, ",") 'Split the lines when a "," is encountered
locate = ReportDetails(0) 'Assosciate to relevant value in array
DOI = ReportDetails(1)
SeverityLevel = ReportDetails(2)
IncidentReport = New ListViewItem
IncidentReport.Text = locate 'Add relevant values to IncidentReport ListViewItem variable
IncidentReport.SubItems.Add(DOI)
IncidentReport.SubItems.Add(SeverityLevel)
lstReports.Items.Add(IncidentReport) 'Transfer IncidentReport to listview
Else
End If
Loop
FileClose(FileNum) 'close file
End If
预期结果是将所有报告位置,日期和严重性级别加载到列表视图中。
对于这个问题的格式也很抱歉,我是堆栈溢出的新手。
答案 0 :(得分:2)
像这样声明ReportDetails
毫无意义:
ReportDetails(2) As String
因为它创建了一个您永远不会使用的数组。在这里:
ReportDetails = Split(ReportTitles, ",")
无论如何您正在创建一个新数组,该数组的长度将由ReportTitles
中的定界符数量确定。如果得知1是该数组的无效索引,则该数组只能包含1个元素,这意味着ReportTitles
不包含任何定界符。
这不是我们必须向您解释的内容,因为您可以通过调试轻松地自己看到它,并且应该始终在此处发布之前进行调试。在代码的顶部设置一个断点,一行一行地浏览并检查每一步的状态。您可以轻松查看ReportTitles
和ReportDetails
的内容以及其他任何内容,以查看它们是否符合您的期望。
如果这里的重点是读取CSV文件,那么您确实应该使用TextFieldParser
类。该类的文档包括一个代码示例。
答案 1 :(得分:0)
这需要.Net Standard 2.1,因此我不确定VB.Net是否可以对SpanAction
方法使用必需的String.Create()
,但是如果受支持,它应该大大优于原始方法
lstReports.Items.Clear()
'Read and "Decrypt" (and I use that term loosely) the file with only a single heap allocation
Dim file As String
Using fs As FileStream = File.OpenRead("ReportTitles.txt")
file = String.Create(fs.Length, fs,
Sub(chars, stream)
For i As Integer = 0 To stream.Length - 1
'THIS IS NOT ENCRYPTION! At best, it's obfuscation.
chars(i) = Chr(fs.ReadByte() Xor 22)
Next
End Sub)
End Using
'Use an actual CSV parser
Using reader As New StringReader(file), _
parser As New TextFieldParser(reader)
parser.TextFieldType = FileIO.FieldType.Delimited
parser.Delimiters = New String() {","}
Dim row As String()
While Not parser.EndOfData
row = parser.ReadFields()
If row.Length >= 3 Then
Dim IncidentReport As New ListViewItem()
IncidentReport.Text = row(0) '
IncidentReport.SubItems.Add(row(1))
IncidentReport.SubItems.Add(row(2))
lstReports.Items.Add(IncidentReport)
End If
End While
End Using
如果您无法使用该版本,则效果不尽如人意,但仍比原始版本更好:
lstReports.Items.Clear()
'Load and "Decrypt" the file
Dim file As String
Using fs As FileStream = File.OpenRead("ReportTitles.txt")
Dim builder As New StringBuilder(fs.Length)
For i As Integer = 0 To fs.Length - 1
'THIS IS NOT ENCRYPTION! At best, it's obfuscation.
builder.Append(Chr(fs.ReadByte() Xor 22))
Next
file = builder.ToString()
End Using
'Use an actual CSV parser
Using reader As New StringReader(file), _
parser As New TextFieldParser(reader)
parser.TextFieldType = FileIO.FieldType.Delimited
parser.Delimiters = New String() {","}
Dim row As String()
While Not parser.EndOfData
row = parser.ReadFields()
If row.Length >= 3 Then
Dim IncidentReport As New ListViewItem()
IncidentReport.Text = row(0) '
IncidentReport.SubItems.Add(row(1))
IncidentReport.SubItems.Add(row(2))
lstReports.Items.Add(IncidentReport)
End If
End While
End Using
在两种情况下,请使用Try/Catch
而不是Dir()
来检查位置是否存在。只需尝试打开文件。 Dir()
花费了额外的磁盘搜寻费用,并且编程中几乎没有什么事情比磁盘I / O慢。