5

これは、私の以前の質問に正直に関連しています。

基本的に、その質問のソリューションはうまく機能しましたが、今では、はるかに大規模な分析アプリケーションで機能するように適応させる必要があります。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())記憶をひどく爆破するつもりです、私はそれを知っています。

4

1 に答える 1

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を使用して回線のタスクをスケジュールすることもできます。

于 2012-11-09T09:37:56.353 に答える