1

選択したファイルに対して、MD5、MD4、SHA1、SHA256、SHA512、RIPEMD160 などの計算を行っています。次のアルゴリズムを作成しましたが、問題があります。

        string finalHash;
        byte[] buffer;
        byte[] oldBuffer;
        int bytesRead;
        int oldBytesRead;
        long streamSize;
        long totalBytesRead = 0;
        try
        {
            if (!String.IsNullOrEmpty(selectedFile))
            {
                _dataStream = File.OpenRead(selectedFile);
                selectedFile = string.Empty;
            }
            foreach (var hashObject in from Control ctrl in Controls where ctrl is CheckBox && ((CheckBox)ctrl).Checked select HashObject)
            {
                //totalBytesRead = 0;
                streamSize = _dataStream.Length;
                buffer = new byte[4096];
                bytesRead = _dataStream.Read(buffer, 0, buffer.Length);
                totalBytesRead += bytesRead;
                do
                {
                    oldBytesRead = bytesRead;
                    oldBuffer = buffer;
                    buffer = new byte[4096];
                    bytesRead = _dataStream.Read(buffer, 0, buffer.Length);
                    totalBytesRead += bytesRead;
                    if (bytesRead == 0)
                    {
                        hashObject.TransformFinalBlock(oldBuffer, 0, oldBytesRead);
                    }
                    else
                    {
                        hashObject.TransformBlock(oldBuffer, 0, oldBytesRead, oldBuffer, 0);
                    }
                    hashCalculationWorker.ReportProgress((int)((double)totalBytesRead * 100 / streamSize));
                } while (bytesRead != 0);
                e.Result = hashObject.Hash;
                finalHash = GenerateHex(hashObject.Hash);
                Invoke(new MethodInvoker(() =>
                                             {
                                                 // Get finalHash 
                                             }));
                hashObject.Dispose();
            }
        }
        catch (Exception)
        {
        }


        private HashAlgorithm HashObject
        {           
            get
            {
                if (isMD5Selected)
                {
                    _hashObject = MD5.Create();
                    isMD5Selected = false;
                }
                else if (isMD4Selected)
                {
                    _hashObject = MD4.Create();
                    isMD4Selected = false;
                }
                else if (isSHA1Selected)
                {
                    _hashObject = SHA1.Create();
                    isSHA1Selected = false;
                }
                ...
                return _hashObject;
                }
            }

上記のコードでは、 foreach ステートメントは、選択されたハッシュ アルゴリズムの数に依存します。最初に選択されたハッシュを正しく計算しますが、2 回目以降は次の反復ごとに間違った値が返されます。どうしたの。誰でも私を助けることができますか?よろしくお願いします。

4

1 に答える 1

2

ループを介して各反復の内容を再読み取りできるように、ストリームをリセットしていません。バッファ管理ロジックはかなり単純化できます。例外がスローされた場合にリソースが解放されるようhashObject.Disposeに、ブロックで呼び出すことが望ましいでしょう。finally

        streamSize = _dataStream.Length;
        buffer = new byte[4096];  
        foreach (var hashObject in from Control ctrl in Controls where ctrl is CheckBox && ((CheckBox)ctrl).Checked select HashObject)  
        {  
            try
            {
                // reset stream position, progress
                _dataStream.Position = 0;
                _totalBytesRead = 0;

                do  
                {  
                    bytesRead = _dataStream.Read(buffer, 0, buffer.Length);  
                    totalBytesRead += bytesRead;  
                    if (_dataStream.Position == _dataStream.Length)  
                    {  
                        hashObject.TransformFinalBlock(buffer, 0, bytesRead);  
                    }  
                    else  
                    {  
                        hashObject.TransformBlock(buffer, 0, bytesRead, buffer, 0);  
                    }  
                    hashCalculationWorker.ReportProgress((int)((double)totalBytesRead * 100 / streamSize));  
                } while (_dataStream.Position < _dataStream.Length);  

                e.Result = hashObject.Hash;  
                finalHash = GenerateHex(hashObject.Hash);  
                Invoke(new MethodInvoker(() =>  
                                             {  
                                                 // Get finalHash   
                                             }));  
            }
            finally 
            {
                hashObject.Dispose();  
            }
        }  

ファイルが大きくない場合のより良い解決策:

ストリームからすべてのデータを一度バッファに読み込み、それを再利用する方がパフォーマンスが向上する場合があります。

        if (!String.IsNullOrEmpty(selectedFile))  
        {  
            buffer = File.ReadAllBytes(selectedFile);  
            streamSize = buffer.Length;
            selectedFile = string.Empty;  
        }  

        foreach (var hashObject in from Control ctrl in Controls where ctrl is CheckBox && ((CheckBox)ctrl).Checked select HashObject)  
        {  
            int offset = 0;
            while (buffer.Length - offset >= streamSize)
            {
                offset += hashObject.TransformBlock(buffer, offset, streamSize, buffer, offset);
                hashCalculationWorker.ReportProgress((int)((double)offset * 100 / streamSize));  
            }

            hashObject.TransformFinalBlock(buffer, offset, buffer.Length - offset);
            hashCalculationWorker.ReportProgress(100);  

            e.Result = hashObject.Hash;  
            finalHash = GenerateHex(hashObject.Hash);  
            Invoke(new MethodInvoker(() =>  
                                         {  
                                             // Get finalHash   
                                         }));  
            hashObject.Dispose();  
        }  
于 2012-07-12T15:44:38.693 に答える