2013-05-01 12 views
5

書き込まれているログファイルを定期的に読み込みたい。 プログラムは定期的にログファイルの内容を読み込み、解析して値を抽出します。しかし、私は毎回ファイル全体を読みたいとは思わない。C# - ファイルの最後の部分を定期的に読み取る最も効果的な方法

特定の行以降のファイルを読み取る方法はありますか?

たとえば、最初の読み取りでは、ファイルは100行です。私はこの値を書き留め、次回は100行目以降の読み込みを開始し、現在のファイルの行番号を保存します。

効率的な方法はありますか? ログファイルは約100MBになり、約5秒ごとに読む必要があります。したがって、毎回完全なファイルを読むのは効率的ではありません。

ご意見をいただければ幸いです。

+2

あなたは、あなたがそのような目的のために意図した複数のファイルやDBにファイルを分割することができTail.NET http://www.codeproject.com/Articles/7568/Tail-NET – itsmatt

+0

に見えるかもしれません。しかし、私はわずか100MBのファイルでどのくらいの利益を提供するか分からない。ストリームは開始インデックスを持つ傾向があります。なぜそれを使用しないのですか? –

答えて

3

私はあなたがこれを探していると思います。オフセットがどのくらいバックトラックしたいのかが分かります。参考:MSDN

using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read)) 
{ 
    fs.Seek(offset, SeekOrigin.End); 
} 

今、ファイルストリームは、しかし、はるかに戻って、あなたがする「オフセット」、そしてあなたがそこから読み取ることができる設定ファイル内を指しています。

+0

... hah、2分遅すぎる;) –

+0

@blandありがとう。私はこの方法を見ていきます。これは私のために働くことができるように見えます。 – madu

2

ログだけが追加されている場合は、ファイルをロックなしで読み取り専用モードで開くことができます。そうすることで、他のプロセスが読んでいる間にそのプロセスに書き込むことができます。

var fs = new FileStream(path,FileMode.Open,FileAccess.Read, FileShare.ReadWrite); 
+0

ファイルの長さを覚えている場合は、次の読み込み時にその場所に 'Seek 'することができます。 – JosephHirn

1

速く汚れたものについては、これを使用します。この場合、ログ・ダンプだ - 私は本当に私が得るどのように多くのラインを気にしない、私はちょうど終わり(numBytes)で束にしたい:

cmdLogReader = new System.IO.StreamReader(cmdLogFileIn); 

if (cmdLogReader.BaseStream.Length < (numBytes - 1)) { 
    return cmdLogReader.ReadToEnd; 
} else { 
    cmdLogReader.BaseStream.Seek(-numBytes, System.IO.SeekOrigin.End); 
    cmdLogReader.ReadLine(); 
    return cmdLogReader.ReadToEnd;   
} 

あなたは常に先頭にBaseStream.Lengthを救うことができるし、それを使用して、次回にどのくらい戻るかを計算します(つまり、numBytesBaseStream.Length - previousBaseStreamLengthなどになります)。これにより、最後の読み取り以降に追加されたものを連続呼び出しできるようになります。

ReadLineコールをスキップしなければならない場合があります。これは、実際にランダムな量をバックトラッキングした後、最も近い行まで移動するためだけです。あなたがライン境界に着陸しようとしていることを知っているならば、ただReadToEndにすることができます。

これはややこしい実装ですが、非常に速いので、私はそれを使用しています。

+0

ありがとうございます。 BaseStream.Lengthプロパティを認識しておらず、このメソッドを使ってファイルを読み込んでいました。私はこの方法を見ていきます。 – madu

1

シークはこれをうまく行うことができます。しかし、私は他の先進的な方法を提供したい。

public static void Read() 
    { 
     var fs = new FileStream(@"G:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
     int lastReadCount = 0; 
     while (true) 
     { 
      var totalCountOfFile = fs.Length; 
      if (lastReadCount < totalCountOfFile) 
      { 
       var buffer = new byte[1024]; 
       int count = fs.Read(buffer, 0, buffer.Length); 
       lastReadCount += count; 
       Display(buffer); 
      } 
      Thread.Sleep(5000); 
     } 
    } 

    private static void Display(byte[] buffer) 
    { 
     var text = Encoding.UTF8.GetString(buffer.Where(p=>p != 0).ToArray()); 
     Console.Write(text); 
    } 
関連する問題