StreamReader 抛出 System.NullReferenceException

StreamReader throws System.NullReferenceException

我在让一段代码正常工作时遇到了一些困难。叙述如下:我有多个具有特定格式的文本文件(因为它们是代码生成的),我需要提取特定的文本块并仅在文本框中显示这些文本块。例如,一个这样的块是 "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:line 238

我在上面的代码中标记了第 238 行。但是,这是该块的输出:

STN 公告:18:50:54 KE4NHW

ASDFASDFASDFASDF

STN 公告:18:50:57 KE4NHW

DFADFADFASWERASDF

STN 公告:18:51:01 KE4NHW

GHSDETGJNHSDFAW34ASDFG

此输出缺少应放入文本框中的 "END ANNOUNCEMENT" 行,但除此之外它确实获得了所有公告。它在每个文本块(末行)中漏掉一行并抛出空引用异常;除此之外,如果我可以显示结束语句,那么至少我们将拥有所有需要提取的文本。

我也尝试了以下更改但没有成功,都产生相同的错误:

改变了 While Not (line Is Nothing)...End While to Do...Loop Until line Is Nothing

更改为 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 块使异常静音之外,我没有其他想法,但这肯定会导致问题。对这个有什么想法吗?

看看这是否有效:

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

Sample data used

我不知道畸形块的可能性有多大,但我可能只是将 "END" 查找为 endToken,这样任何类型块的结尾都会停止捕获。它给了它重新同步的机会。

或者块结束信号可以包括任何块的开始。在这种情况下,您可以手动添加 "END ANNOUNCEMENT" 以保持一致性或其他内容以注意检测到格式错误的块。这些内容可能包括非公告数据。

此外,它使用 StringBuilder 而不是无休止地乱用 UI 控件。字符串是不可变的,因此附加到文本 属性 意味着一遍又一遍地重建它。当捕获的线超过某个点时,这应该会加快速度。