2011-05-26 100 views
0

我正在使用以下函數爲SQL備份文件生成MD5 \ SH1哈希。 這工作得很好,有進展報告等,但如果使用大型文件很慢。生成MD5和SHA1

我可以在SH1的同一時間生成MD5,而不必兩次處理文件,使用時間加倍嗎?將MD5結果轉換爲SHA1怎麼辦?

Imports System 
Imports System.IO 
Imports System.Security.Cryptography 
Imports System.Text 


Public Class ASyncFileHashAlgorithm 
Protected hashAlgorithm As HashAlgorithm 
Protected m_hash As Byte() 
Protected cancel As Boolean = False 
Protected m_bufferSize As Integer = 4096 
Public Delegate Sub FileHashingProgressHandler(ByVal sender As Object, _ 
            ByVal e As FileHashingProgressArgs) 
Public Event FileHashingProgress As FileHashingProgressHandler 

Public Sub New(ByVal hashAlgorithm As HashAlgorithm) 
    Me.hashAlgorithm = hashAlgorithm 
End Sub 

Public Function ComputeHash(ByVal stream As Stream) As Byte() 
    cancel = False 
    m_hash = Nothing 
    Dim _bufferSize As Integer = m_bufferSize 
    ' this makes it impossible to change the buffer size while computing 
    Dim readAheadBuffer As Byte(), buffer As Byte() 
    Dim readAheadBytesRead As Integer, bytesRead As Integer 
    Dim size As Long, totalBytesRead As Long = 0 

    size = stream.Length 
    readAheadBuffer = New Byte(_bufferSize - 1) {} 
    readAheadBytesRead = stream.Read(readAheadBuffer, 0, _ 
            readAheadBuffer.Length) 

    totalBytesRead += readAheadBytesRead 

    Do 
     bytesRead = readAheadBytesRead 
     buffer = readAheadBuffer 

     readAheadBuffer = New Byte(_bufferSize - 1) {} 
     readAheadBytesRead = stream.Read(readAheadBuffer, 0, _ 
             readAheadBuffer.Length) 

     totalBytesRead += readAheadBytesRead 

     If readAheadBytesRead = 0 Then 
      hashAlgorithm.TransformFinalBlock(buffer, 0, bytesRead) 
     Else 
      hashAlgorithm.TransformBlock(buffer, 0, bytesRead, buffer, 0) 
     End If 

     RaiseEvent FileHashingProgress(Me, New _ 
          FileHashingProgressArgs(totalBytesRead, size)) 
    Loop While readAheadBytesRead <> 0 AndAlso Not cancel 

    If cancel Then 
     Return InlineAssignHelper(m_hash, Nothing) 
    End If 

    Return InlineAssignHelper(m_hash, hashAlgorithm.Hash) 
End Function 

Public Property BufferSize() As Integer 
    Get 
     Return m_bufferSize 
    End Get 
    Set(ByVal value As Integer) 
     m_bufferSize = value 
    End Set 
End Property 

Public ReadOnly Property Hash() As Byte() 
    Get 
     Return m_hash 
    End Get 
End Property 

'Public Sub Cancel() 
' cancel = True 
'End Sub 

Public Overrides Function ToString() As String 
    Dim hex As String = "" 
    For Each b As Byte In Hash 
     hex += b.ToString("x2") 
    Next 

    Return hex 
End Function 
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, _ 
               ByVal value As T) As T 
    target = value 
    Return value 
End Function 
End Class 


Public Class FileHashingProgressArgs 
Inherits EventArgs 
Public Property TotalBytesRead() As Long 
    Get 
     Return m_TotalBytesRead 
    End Get 
    Set(ByVal value As Long) 
     m_TotalBytesRead = Value 
    End Set 
End Property 
Private m_TotalBytesRead As Long 
Public Property Size() As Long 
    Get 
     Return m_Size 
    End Get 
    Set(ByVal value As Long) 
     m_Size = Value 
    End Set 
End Property 
Private m_Size As Long 

Public Sub New(ByVal totalBytesRead__1 As Long, ByVal size__2 As Long) 
    TotalBytesRead = totalBytesRead__1 
    Size = size__2 
End Sub 
End Class 

以下是我如何使用上面生成一個散列:

Shared hasher As New ASyncFileHashAlgorithm(SHA1.Create()) 

Private Function Test(Byval (strFilePathAndName, as String) 


Dim stream As IO.Stream = DirectCast(File.Open(strFilePathAndName, _ 
               FileMode.Open), Stream) 

     AddHandler hasher.FileHashingProgress, _ 
        AddressOf OnFileHashingProgress 

     Dim t = New Thread(AddressOf hasher.ComputeHash) 
     t.Start(stream) 
     While t.IsAlive 
      Application.DoEvents() 
     End While 


     'LblMD5.Text = hasher.ToString??? 
     LblSHA1.Text = hasher.ToString 

     stream.Dispose() 

End Sub 

Public Sub OnFileHashingProgress(ByVal sender As Object, _ 
           ByVal e As FileHashingProgressArgs) 

    SetControlPropertyValue(uxChildForm.ProgressBar, "Position", _ 
          CInt(e.TotalBytesRead/e.Size * 100)) 

End Sub 
+0

出於好奇,你爲什麼要兩個哈希函數? SHA不夠用嗎?而且你不能將MD5轉換成SHA,反之亦然。 – 2011-05-26 12:27:00

+0

這兩個值都會生成並傳遞給使用MD5或SHA來驗證備份的客戶端。在理想的世界裏,他們都會用一種方法! – madlan 2011-05-26 12:30:53

回答

1

ToString方法可以創建大型字符串巨大的開銷,因爲級聯是昂貴的(它創建大的臨時緩存)和你經常這樣做。改用StringBuilder(用正確尺寸初始化)。