提高大字符串正则表达式的性能

时间:2013-07-09 13:46:53

标签: c# regex

我目前在代码中使用正则表达式,以便从富文本文档中获取大字符串。正则表达式查找任何嵌入的图像并将它们解析为一个字节数组,我可以将其转换为LinkedResource。我需要将RTF从我的应用程序中的RichTextBox转换为有效的HTML文档,然后转换为可以自动发送的MIME编码消息。

常规表达式的问题是图像的字符串部分非常大,所以我觉得正则表达式试图匹配整个字符串中的许多可能性,实际上,我只需要查看该部分的开头和结尾。下面的正则表达式作为可选子句包含在更大的正则表达式中,例如someRegexStringA + "|" + imageRegexString + "|" + "someRegexStringB"

我可以做些什么来确保在大字符串中检查的次数减少,这样我的应用程序在解析大量图像数据时似乎不会冻结?

// The Regex itself
private static string imageRegexString = @"(?<imageCheck>\\pict)"                  // Look for the opening image tag
                                       + @"(?:\\picwgoal(?<widthNumber>[0-9]+))"   // Read the size of the image's width
                                       + @"(?:\\pichgoal(?<heightNumber>[0-9]+))"  // Read the size of the image's height
                                       + @"(?:\\pngblip(\r|\n))"                   // The image is the newline after this portion of the opening tag and information
                                       + @"(?<imageData>(.|\r|\n)+?)"              // Read the bitmap
                                       + @"(?:}+)";                                // Look for closing braces

// The expression is compiled so it doesn't take as much time during runtime
private static Regex myRegularExpression = new Regex(imageRegexString, RegexOptions.Compiled);

// Iterate through each image in the document
foreach(Match image in myRegularExpression.Matches(myDocument))
{
    // Read the image height and width
    int imageWidth = int.Parse(image.Groups["widthNumber"].Value);
    int imageHeight = int.Parse(image.Groups["heightNumber"].Value);

    // Process the image
    ProcessImageData(image.Groups["imageData"].Value);
}

1 个答案:

答案 0 :(得分:1)

首先,我依稀记得有一个带有富文本编辑器的InfoPath表单可以导出为HTML - 所以你可能想看一下(虽然我们仍然需要单独附加图像)

至于你的模式:它非常简单,只有一条可疑线:

(?<imageData>(.|\r|\n)+?)

这有几个潜在的问题:

  • +?是懒惰的,对于长字符串会导致大量的回溯,这可能效率低下。
  • .|\r|\n似乎效率也很低。您可以使用SingleLine修饰符(或inline (?s:...)) 顺便说一句,. already matches \r
  • (.|\r|\n) - 这是一个捕获组,与您在其他地方使用的(?:...)组不同。我怀疑这是 kill 你 - 在.Net中,每个字符都作为Capture保存在堆栈中。你不希望这样。

我建议使用possessive group,以保证安全:

(?<imageData>(?>[^}]+))

当然,由于其他更改,模式也可能很慢:someRegexStringAsomeRegexStringB