使用正则表达式读入文件?

时间:2012-11-05 20:07:06

标签: c# .net regex streamreader

这与an earlier question of mine.

切线相关

基本上,该问题的解决方案效果很好,但现在我需要使其适应更大的分析应用程序。简单地使用StreamReader.ReadToEnd()是不可接受的,因为我将要阅读的一些文件非常非常大。如果出现了错误并且有人忘了清理,理论上它们可能是千兆字节。显然,我不能只是阅读到底。

不幸的是,正常的读取行也是不可接受的,因为我读入的一些数据行包含堆栈跟踪 - 显然它们在格式化中使用/r/n。理想情况下,我想告诉程序向前读取,直到匹配正则表达式,然后返回。在.net中有任何功能吗?如果没有,我可以就如何写它来获得一些建议吗?

编辑:为了让我更容易理解我的问题,这里粘贴了改编代码的一些重要部分:

foreach (var fileString in logpath.Select(log => new StreamReader(log)).Select(fileStream => fileStream.ReadToEnd()))
{
    const string junkPattern = @"\[(?<junk>[0-9]*)\] \((?<userid>.{0,32})\)";
    const string severityPattern = @"INFO|ERROR|FATAL";
    const string datePattern = "^(?=[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})";
    var records = Regex.Split(fileString, datePattern, RegexOptions.Multiline);
    foreach (var record in records.Where(x => string.IsNullOrEmpty(x) == false))
    ......

问题在于Foreach。 .Select(fileStream => fileStream.ReadToEnd())会严重破坏记忆,我只知道它。

1 个答案:

答案 0 :(得分:1)

首先,您应该将const定义移动到类声明 - 编译器将为您执行此操作,但这应该由您自己完成,只是为了更好的代码可读性。

正如@Blam所提到的,你应该使用StringBuilderStreamReader.ReadLine成对,如下所示:

foreach(var filePath in logpath)
{
    var sbRecord = new StringBuilder();
    using(var reader = new StreamReader(filePath))
    {
        do
        {
            var line = reader.ReadLine();
            // check start of the new record lines
            if (Regex.Match(line, datePattern) && sbRecord.Length > 0)
            {
                // your method for log record
                HandleRecord(sbRecord.ToString());
                sbRecord.Clear();
                sbRecord.AppendLine(line);
            }
            // if no lines were added or datePattern didn't hit
            // append info about current record
            else
            {
                sbRecord.AppendLine(line);
            }
        } while (!reader.EndOfStream)
    }
}

如果我对您的问题一无所知,请在评论中澄清 此外,您可以使用ThreadPool来安排线路的任务,只是为了提高应用程序的速度。