2012-11-05 17 views
5

これは接線と関連していますan earlier question of mine.正規表現を使ってファイルを読み込みますか?

本質的に、この問題の解決策は素晴らしいものでしたが、今はもっと大きな分析アプリケーションで動作するように調整する必要があります。ちょうどStreamReader.ReadToEnd()を使用するだけでは、私が読んでいるファイルのいくつかは非常に非常に大きいので、受け入れられません。間違いがあり、誰かがクリーンアップするのを忘れた場合、理論的にはギガバイト大きくなる可能性があります。明らかに、私はそれを最後まで読むことはできません。

残念ながら、私が読んでいるデータの行の中にはスタックトレースが含まれているので、通常の読み取り行も受け入れられません。彼らは明らかに書式設定で/r/nを使用しています。理想的には、私はそれが正規表現のために一致するまで前方に読むようにプログラムに指示したいと思います。これを行うための機能はありますか?そうでない場合、私はそれを書く方法についていくつかの提案を得ることができますか?

編集:それは少し簡単に私の質問に従わせるためには、ここでの適応コードの重要な部分のいくつかのペーストです:

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

また、このようなタスクでRegExを使用することを本当に気にしない主な理由の1つがあります。単純なパーサーを作成した場合は、単純に新しい行を処理するためにそれを適用することができます。 –

+0

@JonathanWood正規表現は、レコード全体を取り出した後、個々のレコードを解析するのに最適です。私は必要なすべての情報を飛ばして、関連するフィールドに直接移動します。問題は、この場合のファイルの入力です。私が持っているファイルを一度に1つのレコードにするだけの柔軟性がないようです。しかし、それは偽のようですね。これは珍しい問題ではありません。 – tmesser

+1

スタックトレースには/ r/nがあります。なぜそれがreadlineを排除しますか? – Paparazzi

答えて

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を使用して、アプリケーションの速度のために、行のタスクをスケジュールすることができます。

+0

テキストストリームを標準化したトークンを解析できないということが絶対に不合理だと感じたので、低レベルでストリームを扱う独自のソリューションをコーディングしました。しかし、基本的に誰かのために、これは多かれ少なかれあなたがしなければならないことです。 – tmesser

+0

@YYYあなたのコードをここで提供することはできますか?私はこれが面白いと思う。 – VMAtm

+0

私はこれをやりたいと思うほど、すぐに銀行ソフトウェアの一部になるだろうし、それゆえに独自のものです。つまり、私が仕事を数日間休んだら、私の議題にあるものの1つは、オープンソースのバージョンを作成してそれを私のgithubに追加することです。今のところ私は基本的に固定バイト数を読み込み、ファイル位置を保持しています。これはプロジェクトのコンテキストではうまくいきますが、一般化された解決策ではありません。その野心は私の最初の仕事を複製/消毒してgithubに加えると続けられます。 – tmesser

関連する問題