2012-04-30 13 views
7

バイトベースの検索と置換を実行する4Gbファイルがあります。私はそれを行うためのシンプルなプログラムを書いていますが、1回だけ検索して置き換えるには時間がかかりすぎます(90分以上)。私が試したいくつかのヘキサエディタは、3分以内にタスクを実行することができ、ターゲットファイル全体をメモリにロードしません。誰も私が同じことを達成できる方法を知っていますか?ここに私の現在のコードは次のとおりです。C#で巨大ファイルを処理する

public int ReplaceBytes(string File, byte[] Find, byte[] Replace) 
    { 
     var Stream = new FileStream(File, FileMode.Open, FileAccess.ReadWrite); 
     int FindPoint = 0; 
     int Results = 0; 
     for (long i = 0; i < Stream.Length; i++) 
     { 
      if (Find[FindPoint] == Stream.ReadByte()) 
      { 
       FindPoint++; 
       if (FindPoint > Find.Length - 1) 
       { 
        Results++; 
        FindPoint = 0; 
        Stream.Seek(-Find.Length, SeekOrigin.Current); 
        Stream.Write(Replace, 0, Replace.Length); 
       } 
      } 
      else 
      { 
       FindPoint = 0; 
      } 
     } 
     Stream.Close(); 
     return Results; 
    } 

検索と置換は途中で4Gb "ファイル"と比較して比較的小さいです。なぜ私のアルゴリズムが遅いのかを簡単に知ることができますが、どのようにしてよりうまくいくのか分かりません。

+8

まず、一度に1バイト以上を読み取ります。 – SLaks

+0

http://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm – SLaks

答えて

3

問題の一部は、ストリームを1バイトずつ読み取っている可能性があります。大きなチャンクを読んで、そのチャンクを置き換えてみてください。私は約8kbから始めて、より大きなか小さいチャンクでテストして、あなたに最高のパフォーマンスを与えるものを見てみましょう。

buffer = new byte[bufferSize];    
currentPos = 0; 
length = (int)Stream .Length; 
while ((count = Stream.Read(buffer, currentPos, bufferSize)) > 0) 
{ 
    currentPos += count; 
    .... 
} 
2

はバッファでそれを読みますどのようにバッファに読み込むか、そしてより良いバイナリ検索/置換アルゴリズムのうちの1つが、より良い結果をもたらすはずです。

+0

Nice answer !!! ThanX。 – hsalimi

1

もう、一度に複数のバイトを読み込む簡単な方法:サイードAmiriの例でこれを組み合わせる

var Stream = new BufferedStream(new FileStream(File, FileMode.Open, FileAccess.ReadWrite)); 

代わりにバイトして、ファイルのバイトを読み取る

3

(あなたが何をしているか、基本的である)は、文字列にサブストリングを見つけるためのより良いアルゴリズムの多く

スタートはここにあります

http://en.wikipedia.org/wiki/String_searching_algorithm

それらの要旨は、あなたができることですあなたの部分文字列を解析することによって、多くのバイトをスキップします。 ABCDEFGHIJKLMNOP

あなたの部分文字列は次のとおりです:あなたはサブ-1の長さをスキップして、最後のバイトに対してチェックNOP

  1. ので、ここで

    4GBのファイルで始まる簡単な例です。 CとPを比較する

  2. これは一致しないため、部分文字列は最初の3バイトではありません
  3. また、Cは部分文字列にありませんあなたは
  4. がPにFの比較(LENストリングの)3つの以上のバイトをスキップすることができ、すべて、ので、一致しない場合、Fは、
  5. 3はPに私を比較スキップ、サブではないなど、など

あなたが一致する場合は、前に進みます。文字が一致しないが部分文字列にある場合は、その時点で比較する必要があります(詳細はリンクを参照してください)

1

memory-mapped filesを試してください。 C#は、バージョン4.0からそれらをサポートしています。

メモリマップファイルには、仮想メモリ内のファイルの内容が含まれています。

永続化ファイルは、ディスク上のソースファイルに関連付けられたメモリマップファイルです。最後のプロセスがファイルの処理を終了すると、データはディスク上のソースファイルに保存されます。 これらのメモリマップファイルは、非常に大きなソースファイルでの作業に適しています。

+0

完全なソースコードを持つ「本当の」良いサンプルですか? – Kiquenet

関連する問題