5

ファイルのCRC32/md5 / sha1 / sha256 / sha384 / sha512を計算するために使用する単純なアプリケーションを設計しようとしていますが、少し障害が発生しました。これはC#で行われています。

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

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

これは、ファイルをメモリに読み込む最初の試みでした。メモリストリームでハッシュアルゴリズムを実行する前に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;
            }
        }
    }
4

3 に答える 3

4

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

.Netのすべてのハッシュは、HashAlgorithmクラスから派生しています。これには2つの方法があります:TransformBlockTransformFinalBlock。したがって、ファイルのチャンクを読み取り、使用するハッシュのTransformBlockメソッドに詰め込んでから、次のブロックに移動できるはずです。ファイルから最後のチャンクを呼び出すことを忘れないTransformFinalBlockでください。これにより、ハッシュを含むバイト配列が取得されます。

今のところ、機能するまで各ハッシュを一度に1つずつ実行し、ハッシュを同時に実行することを心配します(タスク並列ライブラリなどを使用)。

于 2012-04-26T15:32:47.680 に答える
4

ハッシュアルゴリズムは、ハッシュ値を段階的に計算できるように設計されています。そのためのC#/。NETの例はここにあります。提供されたコードを簡単に変更して、各ステップで複数のハッシュアルゴリズムインスタンスを更新できます。

于 2012-04-26T15:30:33.853 に答える
-1

これは、TPLデータフローオブジェクトで足を濡らす絶好の機会かもしれません。1つのスレッドでファイルを読み取り、データをに投稿しますBroadcastBlock<T>。は6つの異なるインスタンスBroadcastBlock<T>にリンクされます。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.
}
于 2012-04-26T16:38:08.323 に答える