tme*_*ser 5 .net c# regex streamreader
从本质上讲,该问题的解决方案效果很好,但现在我需要使其适应更大的分析应用程序.简单地使用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))
......
Run Code Online (Sandbox Code Playgroud)
问题在于Foreach. .Select(fileStream => fileStream.ReadToEnd())会严重炸掉记忆,我才知道.
首先,您应该将 const 定义移至类声明中 - 编译器将为您执行此操作,但这应该由您自己完成,只是为了更好的代码可读性。
正如@Blam提到的,你应该成对使用StringBuilder和StreamReader.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)
}
}
Run Code Online (Sandbox Code Playgroud)
如果我不明白您的问题,请在评论中澄清。
此外,您还可以使用ThreadPool来安排生产线的任务,以提高应用程序的速度。