2015-11-14 2 views
2

Мне нужна процедура VBA для вычисления хеша MD5 содержимого файла. Я нашел несколько примеров (например, here), но я обнаружил, что они разбились, когда имя файла содержит определенные символы Unicode, поэтому я пытаюсь настроить код, чтобы этого избежать.VBA вычислить хэш MD5 на содержимое файла

Этот код не приводит к ошибке, но также не возвращает правильный MD5-хэш. Что не так?

Public Function FileToMD5Hex(sFileName As String) As String 
    Dim enc 
    Dim bytes 
    Dim outstr As String 
    Dim pos As Integer 
    Set enc = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider") 
    'Convert the string to a byte array and hash it 
    bytes = GetFileBytes(sFileName) 
    bytes = enc.ComputeHash_2((bytes)) 
    'Convert the byte array to a hex string 
    For pos = 1 To LenB(bytes) 
     outstr = outstr & LCase(Right("0" & Hex(AscB(MidB(bytes, pos, 1))), 2)) 
    Next 
    FileToMD5Hex = outstr 
    Set enc = Nothing 
End Function 

Private Function GetFileBytes(path As String) As Byte() 
    Dim fso As Object 
    Set fso = CreateObject("scripting.FileSystemObject") 

    Dim fil As Object 
    Set fil = fso.GetFile(path) 

' Dim fpga As Variant 
    GetFileBytes = fil.OpenAsTextStream().Read(fil.Size) 

    Set fil = Nothing 
    Set fso = Nothing 
End Function 

ответ

3

Есть некоторые симв последовательности, которые Scripting.FileSystemObject не могут обрабатывать должным образом как TextStream.

Использование ADODB.Stream ActiveX для извлечения массива байтов из файла. Он отлично работает как с текстовыми, так и с двоичными типами данных, а также позволяет изменять кодировку строки (FSO работает только с ASCII и Unicode и только с файлами).

Function GetFileBytes(strPath As String) As Byte() 
    With CreateObject("ADODB.Stream") 
     .Type = 1 ' adTypeBinary 
     .Open 
     .LoadFromFile (strPath) 
     GetFileBytes = .Read() 
    End With 
End Function 

Еще одна обработка двоичных данных ActiveX - SAPI.spFileStream. Одно из самых важных преимуществ - позволяет загружать только часть файла в память (в некоторых случаях при сравнении больших файлов это может значительно увеличить производительность, проверяя md5 на куски).

Function GetFileBytes(strPath As String) As Byte() 
    Dim arrContent As Variant 
    With CreateObject("SAPI.spFileStream") 
     .Open strPath, 0 
     .Read arrContent, CreateObject("Scripting.FileSystemObject").GetFile(strPath).Size 
     .Close 
    End With 
    GetFileBytes = arrContent 
End Function 
+0

Хороший код (я буду использовать 'ADODB.Stream' вместо Open #F для двоичного чтения' и' Get' с этого момента). ** Однако есть недостающий компонент: ** у вас есть пример функции System.Security.Cryptography, загружающей последовательные фрагменты байтов в один хэш-расчет? –

+0

Обновление: пользователь Florent B. отправил ответ с данными, переданными в куски в службу хеширования MD5 в [этом ответе на StackOverflow] (https://stackoverflow.com/a/36331066/362712). Это будет очень хорошо работать с вашим ' Реализация SAPI.spFileStream'. –

Смежные вопросы