Как проверить скопированный файл на VB.Net

#.net #vb.net #visual-studio-2017

#.net #vb.net #visual-studio-2017

Вопрос:

В настоящее время я создаю приложение, которое переносит миллионы изображений (.TIF) с одного NAS на другой, и я хочу выполнить проверку, которая позволит мне проверить, были ли файлы скопированы правильно.

Я копирую с помощью функции, которая делает это:

 Public Function CopyFiles(ByVal origin As String, ByVal copiedFile As String)
    Try
        'Check if file exists
        If File.Exists(copiedFile) = False Then
            My.Computer.FileSystem.CopyFile(origin, copiedFile)
            Log("File copied  succsessfully")
        Else
            Log("File already exists")
        End If
        Return True
    Catch ex As Exception
        Log("Error while copying file "   origin.ToString   " Error:"   ex.ToString)
    End Try
    Return False
  

У меня действительно была эта функция сравнения файлов:

 Private Function FileCompare(ByVal file1 As String, ByVal file2 As String) As Boolean
    'Compara byte a byte que los archivos sean iguales.
    'ACTUALMENTE NO SE UTILIZA
    Dim file1byte As Integer
    Dim file2byte As Integer
    Dim fs1 As FileStream
    Dim fs2 As FileStream
    Try

        ' Determine if the same file was referenced two times.
        If (file1 = file2) Then
            ' Return 0 to indicate that the files are the same.
            Return True
        End If

        ' Open the two files.
        fs1 = New FileStream(file1, FileMode.Open)
        fs2 = New FileStream(file2, FileMode.Open)

        ' Check the file sizes. If they are not the same, the files
        ' are not equal.
        If (fs1.Length <> fs2.Length) Then
            ' Close the file
            fs1.Close()
            fs2.Close()

            ' Return a non-zero value to indicate that the files are different.
            Return False
        End If

        ' Read and compare a byte from each file until either a
        ' non-matching set of bytes is found or until the end of
        ' file1 is reached.
        Do
            ' Read one byte from each file.
            file1byte = fs1.ReadByte()
            file2byte = fs2.ReadByte()
        Loop While ((file1byte = file2byte) And (file1byte <> -1))

        ' Close the files.
        fs1.Close()
        fs2.Close()

        ' Return the success of the comparison. "file1byte" is
        ' equal to "file2byte" at this point only if the files are 
        ' the same.
        If ((file1byte - file2byte) = 0) Then
            'Log("******* Archivo Comparado correctamente= "   file1.ToString   "  "   file2.ToString   " *******")
            Return True
        Else
            Log("******* ERROR: al comparar archivos: "   file1.ToString   "  "   file2.ToString   " *******")
            Return False
        End If


    Catch ex As Exception
        Log("******* ERROR, excepcion al comparar archivos: "   file1.ToString   " VS "   file2.ToString   " "   ex.ToString.ToUpper   " *******")
        Return False
    End Try
    Return True
End Function
  

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

Пока что я реализовал то, что я проверяю, существует ли скопированный файл, но это не гарантирует мне, что он не был скопирован с какими-либо проблемами.

Итак, мои идеи таковы:

  • Создайте функцию, которая открывает и закрывает файл, просто чтобы проверить, может ли он открыться.

  • Создайте функцию, которая сравнивает размер исходного файла и скопированного, но я не знаю, может ли быть какой-либо случай, когда скопированный файл имеет тот же размер, но с ошибками.

  • Просто оставьте функцию, которая проверяет, существует ли скопированный файл, поскольку до сих пор во всех моих тестах у меня не возникало никаких проблем с моими скопированными изображениями.

Комментарии:

1. Почему вы хотите снова изобрести колесо. Разве уже не существует программ, которые сделают это за вас? Возьмем, к примеру, robocopy

2. @Storax Поскольку весь процесс включает в себя обновление и вставку нескольких баз данных, я решил создать приложение для всего этого.

3. Хорошо, без проблем, я просто хотел дать вам этот совет / tipp.

4. Я действительно ценю это

5. Вам не нужно сравнивать байт за байтом, вы можете сравнивать массивы байтов — это может быть быстрее. Для других методов сравнения ознакомьтесь с CRC, хэшами и контрольными суммами

Ответ №1:

Обычный способ сделать это — хэшировать файлы. MD5 — это обычная хэш-функция, используемая для этой цели, и это быстрее, чем перебирать каждый байт и сравнивать их. Измените свой код на следующий:

 Private Function FileCompare(ByVal file1 As String, ByVal file2 As String) As Boolean
    'Compara byte a byte que los archivos sean iguales.
    'ACTUALMENTE NO SE UTILIZA
    Dim file1byte As Integer
    Dim file2byte As Integer
    Dim fs1 As FileStream
    Dim fs2 As FileStream
    Try

        ' Determine if the same file was referenced two times.
        If (file1 = file2) Then
            ' Return 0 to indicate that the files are the same.
            Return True
        End If

        ' Open the two files.
        fs1 = New FileStream(file1, FileMode.Open)
        fs2 = New FileStream(file2, FileMode.Open)

        ' Check the file sizes. If they are not the same, the files
        ' are not equal.
        If (fs1.Length <> fs2.Length) Then
            ' Close the file
            fs1.Close()
            fs2.Close()

            ' Return a non-zero value to indicate that the files are different.
            Return False
        End If

        Try
            Dim file1Hash as String = hashFileMD5(file1)
            Dim file2Hash as String = hashFileMD5(file2)

            If file1Hash = file2Hash Then
                Return True
            Else
                Return False
            End If

        Catch ex As Exception
            Return False
        End Try


    Catch ex As Exception
        Log("******* ERROR, excepcion al comparar archivos: "   file1.ToString   " VS "   file2.ToString   " "   ex.ToString.ToUpper   " *******")
        Return False
    End Try
    Return True
End Function
Private Function hashFileMD5(ByVal filepath As String) As String
    Using reader As New System.IO.FileStream(filepath, IO.FileMode.Open, IO.FileAccess.Read)
        Using md5 As New System.Security.Cryptography.MD5CryptoServiceProvider
            Dim hashBytes() As Byte = md5.ComputeHash(reader) 
            Return System.Text.Encoding.Unicode.GetString(hashBytes) 
        End Using
    End Using
End Function
  

Кроме того, я настоятельно рекомендую запускать задачи параллельно, поскольку вы обрабатываете много файлов. Используйте Parallel.ForEach , если вы используете .NET Framework 4 .

Комментарии:

1. Параллельный запуск миллионов копий не приведет к каким-либо последствиям или возникновению какой-либо возможной ошибки?

2. Вы можете установить максимальную степень параллельности потоков с помощью MaxDegreeOfParallelism , но в этом нет необходимости. Он автоматически будет использовать любое количество потоков, предоставляемое базовым планировщиком. Для получения дополнительной информации вы можете прочитать документацию ParallelOptions.MaxDegreeOfParallelism . Таким образом, в случае, который вы объяснили, я думаю, это не должно вызвать никаких проблем. Я использую ту же функцию для создания документов в приложении, где параллельно создается до 250 документов, и это отлично работает. Протестируйте его.

3. Параллельная библиотека задач (TPL) не запускает миллионы копий параллельно. Он достаточно умен, чтобы создавать только ограниченное количество потоков на основе количества процессорных ядер. Затем он автоматически распределяет (возможно, миллионы) задач между этими потоками.

4. Спасибо, НО, как написано, функция FileCompare всегда выдает ошибку! Вы должны закрыть файловые потоки fs1 и fs2 перед передачей имен файлов в hashFileMD5.