2012-04-26 15 views
5

ファイルのCRC32/md5/sha1/sha256/sha384/sha512を計算するために使用する簡単なアプリケーションを設計しようとしていますが、私はいくつかのロードブロッキングを実行しました。これはC#で行われています。1つのファイルを同時に複数の方法でハッシュするには?

これをできるだけ効率的にやりたいと思っています。元の考えでは、処理前にまずメモリースティックにファイルを読み込むことでしたが、すぐに非常に大きなファイルがメモリ不足になることがわかりました非常に迅速に。ですから、代わりにファイルストリームを使用する必要があるようです。問題は、一度に1つのハッシュ関数しか実行できないということです。ファイルストリームを使用すると、各ハッシュが完了するまでに時間がかかります。

ファイルの小さなビットをメモリに読み込み、6つのアルゴリズムすべてで処理してから、別のチャンクに移動するとどうなりますか?またはハッシュがうまくいかないのですか?

これは、ファイルをメモリに読み込む私の最初の試みでした。私は前のMemoryStreamにハッシュアルゴリズムを実行するメモリにCDイメージを読み込むしようとしたとき、それは失敗しました:

private void ReadToEndOfFile(string filename) 
    { 
     if (File.Exists(filename)) 
     { 
      FileInfo fi = new FileInfo(filename); 
      FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); 
      byte[] buffer = new byte[16 * 1024]; 

      //double step = Math.Floor((double)fi.Length/(double)100); 

      this.toolStripStatusLabel1.Text = "Reading File..."; 
      this.toolStripProgressBar1.Maximum = (int)(fs.Length/buffer.Length); 
      this.toolStripProgressBar1.Value = 0; 

      using (MemoryStream ms = new MemoryStream()) 
      { 
       int read; 
       while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        ms.Write(buffer, 0, read); 
        this.toolStripProgressBar1.Value += 1; 
       } 

       _ms = ms; 
      } 
     } 
    } 

答えて

3

ほとんどの方法がありますが、すべてを一度にメモリに読み込む必要はありません。

.Netのすべてのハッシュは、HashAlgorithmクラスに由来します。これには2つの方法があります:TransformBlockTransformFinalBlockです。そのため、ファイルのチャンクを読み込み、使用したいハッシュのTransformBlockメソッドに入れてから、次のブロックに移動する必要があります。ファイルから最後のチャンクのためにTransformFinalBlockを呼び出すことだけを覚えておいてください。これはあなたにハッシュを含むバイト配列を取得するものです。今の

それは同時にハッシュを実行している心配、その後、働いてまで、私はちょうど(タスク並列ライブラリのようなものを使用して)、一度にそれぞれのハッシュいずれかを実行します

+0

これはMD5を使用して動作するようにしましたが、プログラムが実行されますが、不正なハッシュが生成されているようです。 私のコードへのリンクは次のとおりです。[link](http://pastebin.com/i3iPwYZv) – agent154

+1

'TransformFinalBlock'を呼び出すときは、' buffer.Length'ではなく 'read'を使用してください。 –

+0

ありがとう!私は昨夜、これを悩ましていました。それを働かせるために何か愚かな探して一緒にハッキングを終了したが、私は助けることができませんでしたが、それは不要だったと感じました。 最後の配列が完全に読み込まれていたのは、最後のチャンクが小さすぎても読み込んでいたためです。最後の部分のサイズが最後の部分のサイズと等しくなるように新しいバイト配列を作成するようになりました。 – agent154

4

ハッシュアルゴリズムを使用すると、インクリメンタルにハッシュ値を計算することができますように設計されています。そのhereのC#/。NETの例を見つけることができます。提供されたコードを簡単に変更して、各ステップで複数のハッシュアルゴリズムインスタンスを更新することができます。

0

これは、取得するための絶好の機会であるかもしれませんあなたの足はTPLデータフローオブジェクトに濡れています。 1つのスレッドでファイルを読み取り、BroadcastBlock<T>にデータを投稿します。 BroadcastBlock<T>は、6つの異なるActionBlock<T>インスタンスにリンクされます。それぞれActionBlock<T>は、あなたの6つのハッシュ戦略の1つに対応します。

var broadcast = new BroadcastBlock<byte[]>(x => x); 

var strategy1 = new ActionBlock<byte[]>(input => DoHash(input, SHA1.Create())); 
var strategy2 = new ActionBlock<byte[]>(input => DoHash(input, MD5.Create())); 
// Create the other 4 strategies. 

broadcast.LinkTo(strategy1); 
broadcast.LinkTo(strategy2); 
// Link the other 4. 

using (var fs = File.Open(@"yourfile.txt", FileMode.Open, FileAccess.Read)) 
using (var br = new BinaryReader(fs)) 
{ 
    while (br.PeekChar() != -1) 
    { 
    broadcast.Post(br.ReadBytes(1024 * 16)); 
    } 
} 

BroadcastBlock<T>は、リンクされたすべてのActionBlock<T>インスタンスへのデータの各チャンクを転送します。

あなたの質問は、このすべてを同時に発生させる方法にもっと焦点を当てているので、私はDoHashの実装を残しておきます。

private void DoHash(byte[] input, HashAlgorithm algorithm) 
{ 
    // You will need to implement this. 
} 
+0

これはマルチスレッド化にとって非常に面白いアプローチのようです。それはネット4.5にあります。どんな理由であれ、私はまだ十分な主流を感じていないので、.net 4.0を使用するために自分自身を説得するのに十分な時間があります。 – agent154

+0

このアプローチはうまくいかないようです。 DoHashはバイトの各入力配列に対して呼び出されます。それらをどのように組み合わせるべきですか? – Petro

関連する問題