逐行读取文本文件需要异常长时间

Reading line by line through text file taking abnormally long time

我遇到一个问题,我需要逐行阅读文本文件,如果满足特定条件,则将每一行放入一个或另一个字符串中。我遇到的问题是它花费了很长时间,我只是想知道是否有更快的做事方式。我已经就如何做到这一点做了很多研究,这是我能想到的最好的。谢谢。 (每次都附加到两个字符串,因为必须在之后直接将两个字符串输出到文本文件)。

内容在一个巨大的文本文件中,其中一条信息从以 "aaa" 开头的行开始。我必须通过查找何时以 "aaa" 开头的行来查看分隔这些信息的文本文件。将一条信息与 fullStr1 或 fullStr2 分开的标准是索引 29 处的字符是空白 space(" ") 与否。谢谢

        Using reader As StreamReader = New StreamReader(file)
            Dim line As String = reader.ReadLine
            Do While (Not line Is Nothing)
                If line.Substring(0, 3) = "aaa" AndAlso line.Substring(29, 1) <> " " Then
                    Do
                        fullStr1 = fullStr1 & line & vbCrLf
                        line = reader.ReadLine
                    Loop While (Not line Is Nothing AndAlso line.Substring(0, 3) <> "aaa")
                ElseIf line.Substring(0, 3) = "aaa" AndAlso line.Substring(29, 1) = " " Then
                    Do
                        fullStr2 = fullStr2 & line & vbCrLf
                        line = reader.ReadLine
                    Loop While (Not line Is Nothing AndAlso line.Substring(0, 3) <> "aaa")
                End If
            Loop
        End Using

一个非常快速和简单的解决方案是对变量 line 和 fullStr 使用 StringBuilder 类型而不是 String 类型。 (参见 https://msdn.microsoft.com/en-us/library/ms172824.aspx)。 字符串是不可变的,这意味着每次您为 line 或 fullStr 变量赋值时,您并没有真正更新内存中的变量值,而是废弃之前分配的内存并分配新内存 space 为变量并将新值分配给新内存space。这是很大的开销,会影响应用程序的性能。

如果您的文本文件足够长,无论您做什么,扫描都需要一段时间。但是您可以做的一件事应该有所帮助,那就是使用 StringBuilder。它正是为这种情况而设计的,比将一个巨大的字符串一段一段地连接在一起效率要高得多。

Dim builder1 As New StringBuilder()
Dim builder2 As New StringBuilder()

Using reader As StreamReader = New StreamReader(file)
   Dim line As String = reader.ReadLine
   Do While (Not line Is Nothing)
      If line.Substring(0, 3) = "aaa" AndAlso line.Substring(29, 1) <> " " Then
         Do
            builder1.AppendLine(line)
            line = reader.ReadLine
         Loop While (Not line Is Nothing AndAlso line.Substring(0, 3) <> "aaa")
      ElseIf line.Substring(0, 3) = "aaa" AndAlso line.Substring(29, 1) = " " Then
         Do
             builder2.AppendLine(line)
             line = reader.ReadLine
         Loop While (Not line Is Nothing AndAlso line.Substring(0, 3) <> "aaa")
      End If
   Loop
End Using

我也会小心你的循环不会得到 "stuck",因为在外循环中没有 reader.ReadLine 调用。如果它进入外循环并且当前行不是以 "aaa" 开头的情况,那么它将永远循环,什么都不做。要做到这一点,您只需在第一行没有 "aaa"。

我知道这不是最佳解决方案,但可能会更快一些。我总是把每一行都放在一个列表中。这有助于使字符串不那么长,然后我可以逐行查看。但是,当您逐行读取时,任何更大的文件都将花费时间,因为它正在读取文件的每个 line/byte。

Private Function ReadInFile(ByVal strFile As String) As List(Of String)
    Dim strLineTemp As String = ""
    Using read As New StreamReader(strFile)
        While read.Peek <> -1
            strLineTemp = read.ReadLine()
            If strLineTemp.Trim <> "" Then
                lstFileData.Add(strLineTemp)
            End If
        End While
    End Using
    Return lstFileData
End Function

这是你想要的吗?我将条件交换为使用正则表达式并删除了内部循环。尽管我会将字符串连接换成 'StringBuilder',但我 运行 的内存不足了一个大文件。

Dim regex As Regex = New Regex("aaa.{25} .*")
    st.Start()
    Using reader As StreamReader = New StreamReader(file)
        Dim line As String = reader.ReadLine
        Do While (Not line Is Nothing)
            If regex.Match(line).Success = False Then

                fullStr1 = fullStr1 & line & vbCrLf
                line = reader.ReadLine
            Else
                fullStr2 = fullStr2 & line & vbCrLf
                line = reader.ReadLine

            End If

        Loop

    End Using