2016-03-31 69 views
2

我有以下功能爲文件生成md5散列。這些函數適用於小文件,但崩潰並生成運行時錯誤7 - 內存不足當我嘗試散列超過250 MB的文件時(我實際上不知道它打破了哪個確切大小,但下面的文件200 MB工作正常)。如何使用VBA爲大文件生成md5哈希?

我不明白爲什麼它打破了在一定的規模,因此,如果任何人都可以對一些啓發我明白了很多。

此外,有什麼我可以做,使功能處理更大的文件?我打算在一個更大的工具中使用這些函數,我需要爲未知大小的文件生成哈希值。大多數將足夠小,目前的功能可以工作,但我也必須能夠處理大型文件。

我得到了我目前的功能,從最upvoted回答這個帖子How to get the MD5 hex hash for a file using VBA?

Public Function FileToMD5Hex(ByVal strFileName As String) As String 
Dim varEnc   As Variant 
Dim varBytes   As Variant 
Dim strOut   As String 
Dim intPos   As Integer 

Set varEnc = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider") 

'Convert the string to a byte array and hash it 
varBytes = GetFileBytes(strFileName) 
varBytes = varEnc.ComputeHash_2((varBytes)) 

'Convert the byte array to a hex string 
For intPos = 1 To LenB(varBytes) 
    strOut = strOut & LCase(Right("0" & Hex(AscB(MidB(varBytes, intPos, 1))), 2)) 
Next 

FileToMD5Hex = strOut 

Set varEnc = Nothing 

End Function 

Private Function GetFileBytes(ByVal strPath As String) As Byte() 
Dim lngFileNum   As Long 
Dim bytRtnVal()   As Byte 

lngFileNum = FreeFile 

'If file exists, get number of bytes 
If LenB(Dir(strPath)) Then 
    Open strPath For Binary Access Read As lngFileNum 
    ReDim bytRtnVal(LOF(lngFileNum)) As Byte 
    Get lngFileNum, , bytRtnVal 
    Close lngFileNum 
Else 
    MsgBox "Filen finns inte" & vbCrLf & "Avbryter", vbCritical, "Filen hittades inte" 
    Exit Function 
End If 

GetFileBytes = bytRtnVal 
Erase bytRtnVal 

End Function 

謝謝

+1

你試圖改變'intPos'到'Long'呢?整數在VBA中是16位的,因此被限制爲32,767。這是一個長時間的拍攝,因爲我認爲這會導致一個「溢出」錯誤,如果這是問題,但值得嘗試,無可厚非 –

+0

@Macro Man感謝您的建議。問題發生在intPos進場之前。錯誤出現在'Private Function GetFileBytes(ByVal strPath As String)As Byte()'的'GetFileBytes = bytRtnVal'中。 – mejchei

回答

3

看起來你達到內存限制。 一個更好的辦法是通過塊計算文件的MD5:

Public Function ComputeMD5(filepath As String) As String 
    Dim buffer() As Byte, svc As Object, hFile%, blockSize&, i& 
    blockSize = 2^16 

    ' open the file ' 

    If Len(Dir(filepath)) Then Else Err.Raise 5, , "file not found" & vbCr & filepath 

    hFile = FreeFile 
    Open filepath For Binary Access Read As hFile 

    ' allocate buffer ' 

    If LOF(hFile) < blockSize Then blockSize = ((LOF(hFile) + 1024) \ 1024) * 1024 
    ReDim buffer(0 To blockSize - 1) 

    ' compute hash ' 

    Set svc = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider") 

    For i = 1 To LOF(hFile) \ blockSize 
    Get hFile, , buffer 
    svc.TransformBlock buffer, 0, blockSize, buffer, 0 
    Next 

    Get hFile, , buffer 
    svc.TransformFinalBlock buffer, 0, LOF(hFile) Mod blockSize 
    buffer = svc.Hash 

    ' cleanup ' 

    svc.Clear 
    Close hFile 

    ' convert to an hexa string ' 

    ComputeMD5 = String$(32, "0") 

    For i = 0 To 15 
    Mid$(ComputeMD5, i + i + 2 + (buffer(i) > 15)) = Hex(buffer(i)) 
    Next 

End Function 
+0

@ Florent B.哇,謝謝!這就像魅力一樣!出於好奇,數組block()的上界值從何而來?他們的意思是什麼? – mejchei

+0

來自excel的打開文件的最大緩衝區爲32,767字節(1024 * 32 -1),所以我選擇少一點:31744字節(1024 * 31)。 –

+0

@ Florent B.我明白了。再次感謝! :) – mejchei