1

タイムスタンプに基づいて解析および結合する必要があるログ ファイルがいくつかあります。それらは次の形式です。

GaRbAgE fIrSt LiNe
[1124 0905 134242422       ] Logs initialized
[1124 0905 134242568 SYSTEM] Good log entry:
{ Collection:
  ["Attribute"|String]
...
[1124 0905 135212932 SYSTEM] Good log entry:

ご覧のとおり、最初の行は必要ありません。
私は現在、いくつかの正規表現を使用して各ファイルを解析しています。1 つの式で、「Logs initialized」行があるかどうかが判断されますが、これは気にせず破棄します。もう1つは、保持して解析する「良好なログエントリ」があるかどうかを判断します。また、適切なログ エントリの一部は複数行にまたがっています。複数の行にあるログを受け入れるだけです。ただし、正規表現の観点からは複数行のログ コメントと区別できないため、コードは現在、最初のガベージ行もキャプチャします。さらに、私が読んだことから、ここでは正規表現は解決策ではありません(正規表現を使用してログファイルを解析する)。

多くのログ ファイルがあり、かなり大きくなる可能性があります。このため、バッファリングして別のファイルに結合する前に、ログごとに一度に 50 行しか読み取っていません。null 以外のファイルが残っている限り、すべてのファイルをループします。以下は、いくつかの条件と変数を説明に置き換えたコード例です。

while (there are non-null files left to read)
     {
        foreach (object logFile in logFiles) //logFiles is an array that stores the log names
        {
           int numLinesRead = 0;
           using (StreamReader fileReader = File.OpenText(logFile.ToString()))
           {
              string fileLine;
              // read in a line from the file
              while ((fileLine = fileReader.ReadLine()) != null && numLinesRead < 50)
              {
                 // compare line to regex expressions
                 Match rMatch = rExp.Match(fileLine);
                 if (rMatch.Success)  // found good log entry
                 {
                 ...

その最初のゴミの行をどのようにスキップしますか? ReadLine()残念ながら、StreamReader はループ内にあり、他の 50 行ごとに 1 行を削除することになるため、単純に 1 行を消費するほど簡単ではありません。
最初の行をすでにスキップしたファイルのリストまたは配列を保持することを考えました(複数回スキップしないようにするため)が、それはちょっと見苦しいです。usingまた、ステートメントを取り除き、ループの前に StreamReader を開くことも考えましたが、それはしたくありません。

投稿後に編集して、実装がまったく正しくない可能性があることに気付きました。StreamReader が閉じて破棄されると、ファイル内の以前の位置が失われると思います。どちらの場合でも、コンストラクトなしで StreamReader を使用する必要usingがありますか、それとも別の種類のファイル リーダーを検討する必要がありますか?

4

2 に答える 2

2

次のようなものを使用できます。

これの代わりに:

using (StreamReader fileReader = File.OpenText(logFile.ToString()))
{
    string fileLine;
    // read in a line from the file
    while ((fileLine = fileReader.ReadLine()) != null && numLinesRead < 50)
    {

これを行う:

int numLinesRead = 0;

foreach (var fileLine in File.ReadLines(logFile.ToString()).Skip(1))
{
    if (++numLinesRead >= 50)
        break;
于 2013-09-10T20:56:59.170 に答える
1

ファイル内の位置のメソッドに別のパラメーターを追加します。最初はゼロで、ループに入る前に行を消費できます。その後、それを使用して、最後のストリームが中断した場所にストリームを配置できます。

例えば

long position = 0;
while position >= 0
{
  position = ReadFiftyLines(argLogFile,0);
}
public long ReadFiftyLines(string argLogFile, long argPosition)
{
   using(FileStream fs = new FileStream(argLogFile,FileMode.Open,FileAccess.Read))
   {
       string line = null;
       if (argPosition == 0)
       {
          line = reader.Readline();
          if (line == null)
          {
             return -1; // empty file
          }
       }
       else
       { 
          fs.Seek(argPosition,SeekOrigin.Begin);
       }
       StreamReader reader = new StreamReader(fs);
       int count = 0;
       while ((line = reader.ReadLine() != null) && (count < 50))
       {
          count++;
          // do stuff with line
       }
       if (line == null)
       {
          return -1; // end of file
       }
       return fs.Position;
   }
}

または何か。

于 2013-09-10T20:57:08.333 に答える