【问题标题】:Reading from text file with Regex使用正则表达式从文本文件中读取
【发布时间】:2014-02-02 09:39:36
【问题描述】:

以下是我为读取文本文件而编写的方法。在阅读时,我需要将行字符串与给定的正则表达式匹配,如果匹配,则需要将行字符串添加到集合中。

private static void GetOrigionalRGBColours(string txtFile)
{
    string tempLineValue;
    Regex regex = new Regex(@"^\d+.?\d* \d+.?\d* \d+.?\d* SRGB$");

    using (StreamReader inputReader = new StreamReader(txtFile))
    {
        while (null != (tempLineValue = inputReader.ReadLine()))                     
        {
            if (regex.Match(tempLineValue).Success
                && tempLineValue != "1 1 1 SRGB"
                && tempLineValue != "0 0 0 SRGB")
            {
                string[] rgbArray = tempLineValue.Split(' ');
                RGBColour rgbColour = new RGBColour() { Red = Convert.ToDecimal(rgbArray[0]), Green = Convert.ToDecimal(rgbArray[1]), Blue = Convert.ToDecimal(rgbArray[2]) };
                originalColourList.Add(rgbColour);
            }
        }
    }
} 

当这个方法对一个有 28653 行的4MB 的文本文件运行时,完成上述方法大约需要 3 分钟。此外,作为上述运行的结果,originalColourList 填充了 582 个项目。

谁能指导我如何提高这种方法的性能?实际文本文件大小可能高达60MB

仅供参考-
正则表达式的正确匹配:0.922 0.833 0.855 SRGB
正则表达式匹配错误:/SRGB /setrgbcolor load def
txt 文件最初是一个 postscript 文件,我已将其保存为 txt 文件以便使用 C# 进行操作。

【问题讨论】:

  • 如果您向我们展示您的正则表达式的正确匹配和错误匹配,您可能会得到更好的答案。这可以帮助我们确定您的正则表达式是否真的需要。
  • 已编辑以包含更多详细信息。

标签: c# .net regex stream


【解决方案1】:

如果你像这样重写它,正则表达式会快得多:

Regex regex = new Regex(@"^\d+(\.\d*)? \d+(\.\d*)? \d+(\.\d*)? SRGB$");

注意两个重要的变化:

  1. 每个. 都使用反斜杠进行转义,以便正则表达式匹配文字点而不是任何字符。
  2. 每个\. 和后面的\d* 作为一个组都是可选的,而不是\. 本身是可选的。

原来的正则表达式很慢,因为\d+.?\d* 包含连续的quantifiers+?*)。当正则表达式引擎尝试匹配以长数字序列开头的行时,这会导致过多的backtracking。例如,在我的机器上,包含 10,000 个零的行需要超过 4 秒 才能匹配。修改后的正则表达式不到 4 毫秒,提高了 1000 倍。

如果你通过了,正则表达式可能会更快(通过一根头发)

RegexOptions.Compiled | RegexOptions.ECMAScript

作为Regex 构造函数的第二个参数。 ECMAScript 告诉正则表达式引擎将\d 视为[0-9],忽略您不关心的 Unicode 数字,如 ༧(藏文 7)。

【讨论】:

  • 迈克尔的解释非常好。
【解决方案2】:

根据您的记录格式,您可以比使用正则表达式更快地解析。不了解您的文件的所有信息,但从您的两个示例来看,这比使用优化的正则表达式快 30%。

        decimal r;
        decimal g;
        decimal b;
        string rec;
        string[] fields;
        List<RGBColour> originalColourList = new List<RGBColour>();

        using (StreamReader sr = new StreamReader(@"c:\temp\rgb.txt"))
        {
            while (null != (rec = sr.ReadLine()))
            {
                if (rec.EndsWith("SRGB"))
                {
                    fields = rec.Split(' ');

                    if (fields.Length == 4 
                        && decimal.TryParse(fields[0], out r) 
                        && decimal.TryParse(fields[1], out g) 
                        && decimal.TryParse(fields[2], out b)
                        && (r+g+b !=0)
                        && (r != 1  && g != 1 && b!=1)
                        )
                    {
                        RGBColour rgbColour = new RGBColour() { Red = r, Green = g, Blue = b };
                        originalColourList.Add(rgbColour);
                    }
                }
            }
        }

只要任何条件为假,if 就会短路,如果一切都为真,您不再需要将所有值转换为十进制。我用这个在大约 12.5 秒内解析了 600 万行。

【讨论】:

    猜你喜欢
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 2018-01-18
    • 1970-01-01
    相关资源
    最近更新 更多