1

同じ LOG ファイルで 1 日に何度も文字列を検索している場合、前回の検索でファイルから読み取った最後の行に移動してから、行ごとに読み取りを開始する方が速いでしょうか? ここで大幅な節約はありますか?

サンプルファイル

プロセス ID ロジック

11111 中間層サーバーで馬鹿げたロジックを実行します。

11111 まだ実行中のロジック

22222 別のユーザーから、中間層サーバーで愚かなロジックを実行します。

11111 ああ、最初のプロセスが完了しました。

22222 2 番目のプロセスで引き続きロジックを実行しています。

最後にロードしたときからファイルの多くの行が必要な場合があります。現在、UltraEdit を使用してファイルを 1 回ロードしてからファイルを更新しますが、これにはまだかなりの時間がかかります。

上記のこの例では、最初のプロセスからの行が必要です。

ノート:

  1. ファイルのサイズは、場合によっては数百 MB になることがあります。
  2. 上記の例は省略されており、各プロセス ID には 100 行のロジックが含まれる場合があります。
  3. ネットワーク経由でログ ファイルにアクセスしています。UE では、ローカル PC にコピーしてからファイルを開くよりも、ネットワーク経由でファイルをロードしてからファイルを更新し続ける方が高速であることがわかりました。
  4. 私は、powershell から実行できる C# コンソール アプリケーションを作成し、必要な行を画面またはファイルにパイプすることを望んでいます。

もう 1 つの質問は、このプロセスを可能な限り効率的にするにはどうすればよいかということです。1. ファイル サイズに使用される C# メソッドについて教えてください。2. ユーティリティの作成に使用するアプリケーションについて教えてください。私はpowershell、C#、C++、perlを持っています

4

2 に答える 2

1

これは、Stream.Seek を使用して可能になります。ストリームの最後の位置を覚えておいて、そこから先に進むだけで済みます。ログ ファイルに行を追加するだけであれば問題なく動作し、同じ行を何度も読み取ってスキャンするよりも確実に高速になります。

既存のコードの一部を投稿していただければ、それを行うためのコードを書くお手伝いもできます。

http://msdn.microsoft.com/en-us/library/system.io.stream.seek.aspx

于 2012-12-15T23:38:45.960 に答える
1

このようなものを自分で実装したかったので、時間をかけて試してみました。FileStreamこれが私が思いついた拡張メソッドです(静的クラスに入れる必要があります) :

public static string ReadLineAndCountPosition(this FileStream fs, ref long position)
{
    //Check if too great a position was passed in:
    if (position > fs.Length)
        return null;
    bool is_carriage_return = false;
    StringBuilder sb = new StringBuilder();
    fs.Seek(position, SeekOrigin.Begin);

    while (position < fs.Length)
    {
        var my_byte = fs.ReadByte();
        position++;
        //Check for newlines
        if (is_carriage_return && my_byte == 10)// \n
            return sb.ToString();
        if (my_byte == 13)                     // \r
            is_carriage_return = true;
        else
        {
            is_carriage_return = false;
            sb.Append((char)my_byte);
        }

    }
    return sb.ToString();//We've consumed the entire file.
}

そして、それを使用するにはReadLineAndCountPosition、単に呼び出して、位置を保存するパラメーターを渡すだけで使用できますlong。しばらくしてから、この位置に単に .Seek() を実行します。

static void Main(string[] args)
{
    FileStream fs = new FileStream("testfile.txt",FileMode.Open);
    long saved_position = 0;

    while(true)
    {
        string current_line = fs.ReadLineAndCountPosition(ref saved_position);
        if (current_line == null || current_line == "SomeSearchString")
            break;
    }

    //Some time later we want to search from the saved position:
    while(true)
    {
        string current_line = fs.ReadLineAndCountPosition(ref saved_position);
        if (current_line == null || current_line == "SecondSearchString")
            break;
    }
}

私は自分でいくつかのテストを実行しましたが、うまく機能しているようです。お困りのことがありましたらお知らせください。うまくいけば、それはあなたを助けます.

于 2012-12-15T23:57:27.277 に答える