Сравнение VB.NET MD5 с использованием больших файлов

Я пытаюсь создать программу в VB.NET 2010 с простой функциональностью. Он должен сравнивать тысячи хэшей MD5, хранящихся в текстовом файле, с текущим хэшем MD5 файла, который программа автоматически вычисляет при открытии файла. Как антивирусный сканер. На самом деле моя программа использует систему ReadAllText для добавления всех хэшей из текстового файла в текстовое поле, а затем сравнивает их.

Все в порядке, когда база данных Md5 (этот текстовый файл с хешами) маленькая, но когда файл становится больше, моя программа просто зависает после открытия, поэтому я решил использовать ReadLine вместо ReadAllText.

Теперь я больше не могу использовать текстовое поле, поэтому дайте мне способ, как я могу их сравнить. Я пробовал способ, но он, похоже, не работает.

Вот мой код с использованием ReadLine.

Проблема в If Read contains(buff.tostring) раньше была Если textbox.text содержит (buff.toString)

Вот код

Try
            TextBox2.Text = e.FullPath
            ListBox3.Items.Add(TextBox2.Text.ToString)
            Me.OpenFileDialog1.FileName = ""
            Dim reader As StreamReader = New StreamReader("def.txt")
            Dim read = reader.ReadLine()
            Dim md5 As New MD5CryptoServiceProvider
            Dim f As New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, &H2000)
            f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read, &H2000)
            md5.ComputeHash(f)
            Dim hash As Byte() = md5.Hash
            Dim buff As New StringBuilder
            Dim hashByte As Byte
            For Each hashByte In hash
                buff.Append(String.Format("{0:X2}", hashByte))
            Next
            f.Close()
            If read.Contains(buff.ToString) Then
                Me.OpenFileDialog1.FileName = e.FullPath
                Form2.ShowDialog()

            End If

        Catch exception1 As Exception
            ProjectData.SetProjectError(exception1)
            Dim ex As Exception = exception1
            ProjectData.ClearProjectError()
        End Try

person KingOfBSOD    schedule 22.01.2015    source источник
comment
Используйте список (из строк) для хранения списка хэш-списков. или используйте File.ReadLines, получите их как массив и используйте его оттуда   -  person Ňɏssa Pøngjǣrdenlarp    schedule 22.01.2015
comment
Как? Будьте более откровенны. Файл очень БОЛЬШОЙ (20 МБ)   -  person KingOfBSOD    schedule 22.01.2015
comment
Было бы хорошо, если бы вы могли изменить мой код и опубликовать его как ответ. Я хотел бы отметить это как ответ на мой вопрос, если вы это сделаете. Спасибо!   -  person KingOfBSOD    schedule 22.01.2015
comment
Вам действительно нужно текстовое поле? Вы требуете, чтобы эта информация отображалась на экране?   -  person the_lotus    schedule 22.01.2015
comment
Затем используйте обычную строковую переменную (Dim data As String). Элемент управления пользовательским интерфейсом, такой как текстовое поле, следует использовать для отображения информации на экране, а не в качестве хранилища данных. В вашем примере кода не используется текстовое поле.   -  person the_lotus    schedule 22.01.2015
comment
Когда программа открывается, все хэши (один хэш на строку) из текстового файла добавляются в скрытое текстовое поле, затем, когда пользователь начинает сканирование, программа получает файлы с помощью SystemFileWatcher и вычисляет их хэши. Если вычисленный хэш совпадает с хэшем из текстового поля, то срабатывает событие   -  person KingOfBSOD    schedule 22.01.2015
comment
Покажите мне, как :3 Я понятия не имею, как сравнивать рассчитанные хэши с хэшами из файла напрямую   -  person KingOfBSOD    schedule 22.01.2015


Ответы (1)


Я бы сначала создал функции, чтобы разделить функциональность. После этого намного легче понять код. Храните хэши в списке, этот список затем может быть закэширован.

Try

    TextBox2.Text = e.FullPath
    ListBox3.Items.Add(TextBox2.Text.ToString)
    Me.OpenFileDialog1.FileName = ""

    Dim allHash As List(Of String) = GetAllHash()
    Dim curHash As String = GetFileHash(e.FullPath)

    If allHash.Contains(curHash) Then
        Me.OpenFileDialog1.FileName = e.FullPath
        Form2.ShowDialog()
    End If

Catch exception1 As Exception
    ProjectData.SetProjectError(exception1)
    Dim ex As Exception = exception1
    ProjectData.ClearProjectError()
End Try

Function GetAllHash() As List(Of String)

    ' Store the data in a list instead
    Return System.IO.File.ReadAllLines("def.txt").ToList()
End Function

Function GetFileHash(ByVal filename As String) As String

    Dim md5 As New MD5CryptoServiceProvider
    ' Only open the file once
    Dim f As New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, &H2000)
    md5.ComputeHash(f)
    Dim hash As Byte() = md5.Hash
    Dim buff As New StringBuilder

    For Each hashByte As Byte In hash
        buff.Append(String.Format("{0:X2}", hashByte))
    Next

    f.Close()

    Return buff.ToString()
End Function
  • Я не компилировал этот код, это просто пример, чтобы показать вам, что можно сделать.
person the_lotus    schedule 22.01.2015
comment
@ F.C.E.365 Я получил e.FullPath из вашего примера. Он не должен зависать для файла размером 20 МБ. Если файл никогда не изменяется, ReadAllLines можно выполнить только один раз, если список хранится где-то, чтобы использовать его в другой раз. - person the_lotus; 22.01.2015