#.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.