VB.NET有没有更快的方法来扫描RichTextBox?

时间:2013-09-30 19:27:58

标签: vb.net loops

我有一个VB.NET应用程序,我用它将各种文件加载到RichTextBox中,然后扫描文档以查找特定的单词。它类似于Word中的Find功能。该应用程序运行良好,直到一个5,150行.sql文件运行它,它需要超过10分钟才能运行完成。

有人可以推荐一种比下面更好的编码方式吗?

    If sqlText.Contains("GRANT") Then

        Dim searchstring As String = "GRANT"

        Dim count As New List(Of Integer)()

        For i As Integer = 0 To rtbFile.Text.Length - 1
            If rtbFile.Text.IndexOf(searchstring, i) <> -1 Then
                count.Add(rtbFile.Text.IndexOf(searchstring, i))
            End If
        Next

        Try
            For i As Integer = 0 To count.Count - 1
                rtbFile.Select(count(i), searchstring.Length)
                rtbFile.SelectionBackColor = Color.Yellow
                rtbFile.SelectionFont = New Font(rtbFile.Font, FontStyle.Bold)
                count.RemoveAt(i)
            Next
        Catch ex As Exception
        End Try

        rtbFile.Select(rtbFile.Text.Length, 0)
        rtbFile.SelectionBackColor = Color.White
        rtbFile.SelectionFont = New Font(rtbFile.Font, FontStyle.Regular)

    End If

4 个答案:

答案 0 :(得分:3)

第一个循环正在杀死性能,你为字符串中的每个字符调用IndexOf。两个循环也可以合并为一个。将其更改为:

rtbFile.SelectionBackColor = Color.Yellow
rtbFile.SelectionFont = New Font(rtbFile.Font, FontStyle.Bold)

For Each m As Match in Regex.Matches(sertbFile.Text, searchstring)
     rtbFile.Select(m.Index, searchstring.Length)
Next

答案 1 :(得分:2)

你在这里发生了一些不好的事情:

首先,以下代码:

For i As Integer = 0 To rtbFile.Text.Length - 1
    If rtbFile.Text.IndexOf(searchstring, i) <> -1 Then
        count.Add(rtbFile.Text.IndexOf(searchstring, i))
    End If
Next

这循环遍历字符串中的每个字符,并从该点向前调用整个字符串上的IndexOf。所以你的50,000个字符的字符串在大字符串上运行IndexOf 50,000次。

您只需要在找到字符串时多次调用IndexOf。找到字符串后,将起始索引增加到该点,并继续仅从该点开始搜索。

接下来,这段代码:

For i As Integer = 0 To count.Count - 1
    ...
    count.RemoveAt(i)
Next

RemoveAt行是不必要的。您已经在列表中循环,因此您不需要在移动时删除这些项目。它的方式,你的循环将跳过列表中的每个其他项目。

答案 2 :(得分:2)

这也可以使用While循环和RichTextBox.Find():

来完成
    Dim searchstring As String = "GRANT"
    Dim index As Integer =  rtbFile.Find(searchstring, 0, RichTextBoxFinds.None)
    While index <> -1
        rtbFile.Select(index, searchstring.Length)
        rtbFile.SelectionBackColor = Color.Yellow
        rtbFile.SelectionFont = New Font(rtbFile.Font, FontStyle.Bold)
        index = rtbFile.Find(searchstring, index + searchstring.Length, RichTextBoxFinds.None)
    End While

答案 3 :(得分:1)

糟糕。我错过了关于IndexOf的一个非常重要的观点(错误地认为它是在最后一场比赛结束时进行的)。见马格努斯的答案。


我不确定瓶颈在哪里(而且很可能是设置选择本身),但这是我的建议,大致按优先顺序排列:

  1. 调用rtbFile.Text一次以避免任何往返底层控件的往返(可能是本机Windows控件?)并使用变量来存储生成的字符串。一旦在.NET中获得字符串,只需继续使用它,除非/直到文本可能更改。如果控件是原生的,那么可能需要很多工作来简单地“获取文本”。

  2. 对计数集合(不是索引)使用正常项目迭代,并且在分配选择时不要从列表的前面删除。从List的前面删除是“昂贵的”,因为它必须在内部向下移动所有项目。此外,删除元素在这里是不必要的,并且充其量是可疑的:因为被修改的集合也正在被迭代,这可能导致不正确的行为(跳过的项目),而不管性能如何。

    < / LI>
  3. 每个循环只调用一次IndexOf 并使用变量来避免重复搜索。这可能不会产生整体影响,但它确实避免了一些“额外”的工作。 IndexOf本身很好,不需要更换。

  4. 因人而异。