有一种快速的方法来解析带有正则表达式的大文件吗?

Ray*_*awn 10 c# regex algorithm

问题:非常非常大的文件我需要逐行解析以从每一行获得3个值.一切正常但解析整个文件需要很长时间.几秒钟内可以做到这一点吗?它的典型时间为1分钟至2分钟.

示例文件大小为148,208KB

我正在使用正则表达式解析每一行:

这是我的c#代码:

private static void ReadTheLines(int max, Responder rp, string inputFile)
{
    List<int> rate = new List<int>();
    double counter = 1;
    try
    {
        using (var sr = new StreamReader(inputFile, Encoding.UTF8, true, 1024))
        {
            string line;
            Console.WriteLine("Reading....");
            while ((line = sr.ReadLine()) != null)
            {
                if (counter <= max)
                {
                    counter++;
                    rate = rp.GetRateLine(line);
                }
                else if (max == 0)
                {
                    counter++;
                    rate = rp.GetRateLine(line);
                }
            }
            rp.GetRate(rate);
            Console.ReadLine();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("The file could not be read:");
        Console.WriteLine(e.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的正则表达式:

public List<int> GetRateLine(string justALine)
{
    const string reg = @"^\d{1,}.+\[(.*)\s[\-]\d{1,}].+GET.*HTTP.*\d{3}[\s](\d{1,})[\s](\d{1,})$";
    Match match = Regex.Match(justALine, reg,
                                RegexOptions.IgnoreCase);

    // Here we check the Match instance.
    if (match.Success)
    {
        // Finally, we get the Group value and display it.

        string theRate = match.Groups[3].Value;
        Ratestorage.Add(Convert.ToInt32(theRate));
    }
    else
    {
        Ratestorage.Add(0);
    }
    return Ratestorage;
}
Run Code Online (Sandbox Code Playgroud)

以下是要解析的示例行,通常约为200,000行:

10.10.10.10 - - [27/Nov/2002:16:46:20 -0500]"GET/solr/HTTP/1.1"200 4926 789

sll*_*sll 16

内存映射文件任务并行库的帮助.

  1. 使用多个随机访问视图创建持久化MMF.每个视图对应于文件的特定部分
  2. 使用参数定义解析方法IEnumerable<string>,基本上是抽象一组未解析的行
  3. Parse(IEnumerable<string>)使用任务操作为每个MMF视图创建和启动一个TPL任务
  4. 每个工作任务都将解析后的数据添加到BlockingCollection类型的共享队列中
  5. 另一个任务侦听BC(GetConsumingEnumerable())并处理已由工作任务解析的所有数据

请参阅MSDN上的管道模式

必须说这个解决方案是为了 .NET Framework >=4


Ree*_*sey 5

现在,您Regex每次调用GetRateLine时都会重新创建您的,每次阅读一行时都会发生这种情况。

如果您提前创建一个 Regex 实例,然后使用非静态Match方法,您将节省 regex 编译时间,这可能会给您带来速度增益。

话虽如此,它可能不会让你从几分钟到几秒钟......