我在使用一段代码时遇到了一些困难。这是叙述:我有多个具有特定格式的文本文件(因为它们是代码生成的),我需要提取特定的文本块并在文本框中仅显示那些文本块。例如,一个这样的块将是“STN COMMENT”“END COMMENT”。此文件可能包含两个,三个甚至10个此类块,并且将具有不同类型的块,其中COMMENT将替换为QUESTION,ANNOUNCEMENT或TRAFFIC。全部以相应的“END”结束。这是我尝试的第一个代码段:
'block to parse only this user's announcements
'dl is variable alias for: Environment.NewLine + Environment.NewLine
txtNetLog.Text = "" 'clears the textbox
TmpFileName = logPath + ByCall + "-" + Format(Now, "dd-MMM-yyyy") + ".tmp" 'sets filename with path defined in module
Try
Using sr As StreamReader = New StreamReader(TmpFileName)
Dim line As String = sr.ReadLine()
While Not (line Is Nothing)
line = sr.ReadLine()
If line.Contains("STN ANNOUNCEMENT") Then '***This is line 238 from exception
Do
txtNetLog.Text = txtNetLog.Text & line + dl
line = sr.ReadLine()
Loop Until line.Contains("END ANNOUNCEMENT")
End If
End While
End Using
Catch ex As Exception
Dim msg As String = "Error: Failure Parsing Temp File For Announcements. Contact Developer" + dl + ex.ToString
Dim title = "Error in StreamReader"
Dim errorFile As System.IO.StreamWriter
Dim errorFileName As String = logPath + "Errors.txt"
errorFile = My.Computer.FileSystem.OpenTextFileWriter(errorFileName, True)
errorFile.Write(msg)
errorFile.Close()
MsgBox(msg, MsgBoxStyle.ApplicationModal, title)
End Try
这产生了以下异常:
System.NullReferenceException:未将对象引用设置为对象的实例。 在GSPASEC_Net_Control.ReviewNetLogFrm.ParseLog(Int32 DataType,Int32 SortType)C:\ Users \ KE4NHW \ Documents \ Visual Studio 2010 \ Projects \ GSPASEC Net Control \ GSPASEC Net Control \ ReviewNetLogFrm.vb:238行
我在上面的代码中标记了238行。但是,这是该块的输出:
STN公告:18:50:54 KE4NHWASDFASDFASDFASDF
STN公告:18:50:57 KE4NHWDFADFADFASWERASDF
STN公告:18:51:01 KE4NHWGHSDETGJNHSDFAW34ASDFG
此输出缺少应放在文本框中的“END ANNOUNCEMENT”行,否则它会获得所有公告。它错过了每个文本块一行(结束行)并抛出了nullreferenceexception;除此之外,如果我可以显示结束语句,那么至少我们将拥有所有需要提取的文本。
我也尝试了以下更改但没有成功,都产生了同样的错误:
更改了“不是”(行无效)...结束时要执行...循环直到行无效
将其更改为Do Until line Is Nothing ... Loop
我最新的测试版本是:
txtNetLog.Text = ""
'block to parse only this user's Comments
TmpFileName = logPath + ByCall + "-" + Format(Now, "dd-MMM-yyyy") + ".tmp"
Try
Using sr As StreamReader = New StreamReader(TmpFileName)
Dim line As String = sr.ReadLine()
Do Until line Is Nothing
line = sr.ReadLine()
If line.Contains("STN COMMENT") Then
Do Until line.Contains("END COMMENT")
txtNetLog.Text = txtNetLog.Text + line + nl + nl
line = sr.ReadLine()
Loop
End If
Loop
End Using
Catch ex As Exception
Dim msg As String = "Error: Failure Parsing Temp File For Comments. Contact Developer" + nl + nl + ex.ToString
Dim title = "Error in StreamReader"
MsgBox(msg, MsgBoxStyle.ApplicationModal, title)
ErrorLogWriter("ErrorLog.txt", msg)
End Try
同样的事情。不在文本框中放置“END COMMENT”,并抛出相同的异常。我的想法不是强迫try块只是让异常沉默,但这肯定会引起问题。对这一个有任何想法吗?
答案 0 :(得分:0)
看看这是否有效:
Dim sb As New StringBuilder
Dim startToken = "STN ANNOUNCEMENT"
Dim endToken = "END ANNOUNCEMENT"
Dim line As String
Using sr As StreamReader = New StreamReader("C:\Temp\LogData.Txt")
Do Until sr.EndOfStream
line = sr.ReadLine
If line.StartsWith(startToken) Then
sb.AppendLine(line)
Do Until sr.EndOfStream OrElse line.StartsWith(endToken)
line = sr.ReadLine
sb.AppendLine(line)
Loop
End If
Loop
End Using
tbLog.Text = sb.ToString
我不知道格式错误的块的可能性是多少,但我可能只是寻找" END"作为endToken
,以便任何类型的块的结束将停止捕获。它给了它重新同步的机会。
或者块结束信号可能包括任何块的开始。在这种情况下,您可以手动添加" END ANNOUNCEMENT"为了均匀性或其他注意到检测到畸形块。这些内容可能包括非ANNOUCEMENT数据。
此外,它使用StringBuilder
而不是无休止地搞乱UI控件。字符串是不可变的,因此附加到Text属性意味着一遍又一遍地重建它。当捕获的线超过某一点时,这应该加快速度。