Сравнение двух файлов на идентичность содержимого

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сравнение двух файлов на идентичность содержимого

Сообщение dimix » 16.03.2005 (Ср) 18:49

Подскажите, пожалуйста, как правильно/оптимально сравнить два файла на предмет идентичности содержимого? Выполнять побайтовое чтение из обоих файлов и сравнивать байты? Или лучше по другому?

KDima
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 759
Зарегистрирован: 14.07.2004 (Ср) 23:14
Откуда: СПб

Сообщение KDima » 16.03.2005 (Ср) 19:27

Похожести или идентичности?

TheString
Abc


TheString

Abc


При сравнивании файлы - различны, но ведь смысл практически идентичен (nothing = nothing :) )
Последний раз редактировалось KDima 16.03.2005 (Ср) 19:33, всего редактировалось 1 раз.
Хороший прогер не тот, кто всё знает, хороший прогер знает, где найти знание.

Последний раз редактировалось: Administrator (15.07.2004 (Вт) 00:01), всего редактировалось 999 раз(а)

VOS
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 72
Зарегистрирован: 04.11.2004 (Чт) 18:01
Откуда: СПб

Сообщение VOS » 16.03.2005 (Ср) 19:27

Код: Выделить всё

Function FilesIdentical(FILE1 as string, FILE2 as string) as boolean
Open FILE1 for binary as #1
Open FILE2 for binary as #2
if lof(1)<>lof(2) then: filesidenctical=false: exit function
s1$=space$(lof(1))
s2$=space$(lof(2))
get #1,,s1$
get #2,,s2$
if s1$<>s2$ then filesidentical=false else filesidentical=true
end function
- Папа, а правда, что форумы делают человека идиотом?
- Гыыы, лол, сынок!

dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сообщение dimix » 16.03.2005 (Ср) 20:21

KDima, интересует полная идентичность.

VOS, я правильно понял, содержимое файлов сравнивается сразу целиком? А если файлы большие, не будет рациональнее сравнивать в цикле по байту, чтобы как можно раньше обнаружить различие и прервать цикл? Или "физически" сравнение s1$<>s2$ будет производиться аналогичным образом?

SHURUP
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 440
Зарегистрирован: 15.09.2004 (Ср) 14:24
Откуда: Ирпень, Украина

Сообщение SHURUP » 17.03.2005 (Чт) 2:54

Пробовал сравнить два фильма - ничего не вышло, выдало обибку.
"R-T-E 14: Out of string space"
F2 писал(а):
Код: Выделить всё
Function Space$(Number  :!:  As Long :!: ) As String

:roll: Так и не узнаю, отличаются фильмы или нет , прийдется оба пересмотреть! :roll:
Нам чужого не надо, но своё мы возьмем, чьё бы оно ни было...

sashar2
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 170
Зарегистрирован: 06.02.2005 (Вс) 19:58

Сообщение sashar2 » 17.03.2005 (Чт) 6:45

Private Sub Form_Load()
Dim ravno as Boolean
Dim data1 as String
Dim data2 as String
Open "c:\1.txt" for binary as #1
Open "c:\2.txt" for binary as #2
if not FileLen("c:\1.txt")=FileLen("c:\2.txt") then
ravno = False
MsgBox "Не равны"
End
End if
data1 = Input(FileLen("c:\1.txt"),1)
data2 = Input(FileLen("c:\2.txt"),2)
if not data1 = data2 then
ravno = False
MsgBox "Не равны"
end
Else
ravno = True
MsgBox "Файлы полностью идентичны"
End
End if
End Sub

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

sashar2
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 170
Зарегистрирован: 06.02.2005 (Вс) 19:58

Сообщение sashar2 » 17.03.2005 (Чт) 6:47

Единственное, что плохо в моем методе, это то что долго достаточно проверяются файлы....

sashar2
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 170
Зарегистрирован: 06.02.2005 (Вс) 19:58

Сообщение sashar2 » 17.03.2005 (Чт) 6:52

Private Sub Form_Load()
Dim ravno As Boolean
Dim data1 As String
Dim data2 As String
Open "c:\1.exe" For Binary As #1
Open "c:\2.exe" For Binary As #2
If LOF(1) <> LOF(2) Then
ravno = False
MsgBox "Не равны"
End
End If
data1 = Space$(LOF(1))
data2 = Space$(LOF(2))
Get #1, , data1
Get #2, , data2
If data1 <> data2 Then
ravno = False
MsgBox "Не равны"
End
Else
ravno = True
MsgBox "Файлы полностью идентичны"
Close #1
Close #2
End
End If
End Sub

Теперь все нормально и проверяет быстро!

sashar2
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 170
Зарегистрирован: 06.02.2005 (Вс) 19:58

Сообщение sashar2 » 17.03.2005 (Чт) 6:57

Кстати почему нельзя скопировать файл вот таким свособом:

Private Sub Form_Load()
Dim data As String
Open "c:\1.exe" For Binary As #1
Open "c:\2.exe" For Binary As #2
Get #1, , data
Put #2, , data
End Sub

Что здесь неправильного? Даже если указать размер записи, что я делаю не так? Просто мне из-за этого приходится делать через Input(...,...) все, а читается долго...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 8:13

Можно. Только вначале зарезервируй буфер, data = String$(LOF(1), 0)
Lasciate ogni speranza, voi ch'entrate.

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 17.03.2005 (Чт) 12:11

Код: Выделить всё
Shell "fc /b C:\File1.ext D:\File2.ext > compare.txt"

dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сообщение dimix » 17.03.2005 (Чт) 13:03

Ennor писал(а):
Код: Выделить всё
Shell "fc /b C:\File1.ext D:\File2.ext > compare.txt"


Ennor, а что это?

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 13:04

Ennor писал(а):
Код: Выделить всё
Shell "fc /b C:\File1.ext D:\File2.ext > compare.txt"

А помоему, работать не будет. В Shell редиректы не срабатывают.
Lasciate ogni speranza, voi ch'entrate.

dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сообщение dimix » 17.03.2005 (Чт) 13:10

Sashar2, а чем твой последний пример отличается от примера VOS (кроме data1 и data2 вместо s1$ и s2$)?

И вообще, ответьте мне кто-нибудь, data1 <> data2 (в примере Sashar2) и s1$<>s2$ (в примере VOS) выдадут результат только после сравнения всех байтов или после нахождения первого же отличия? Ведь если после полного сравнения - то это же не оптимально!

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 17.03.2005 (Чт) 13:17

Это программа File Compare из состава операционной системы. Сомневаюсь, что получится на VB написать что-то более быстрое, чем она.

Но если Alibek говорит, что в шелле не работают редиректы, значит, так оно и есть :(. Интересно, а в ShellExecute() - тоже не работают? Ну, тогда, полагаю, CreateProcess() решит все проблемы :).

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 13:47

В ShellExecute тоже не работают.
Чтобы их заюзать, надо использовать CreatePipe (с перенаправлением ввода-вывода). Есть вероятность, что конструкция shell("cmd /c ping local >result"), но вероятность невысокая. Другой способ - создавать bat-файл и запускать из него.
Lasciate ogni speranza, voi ch'entrate.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 13:49

Хм... Надо же, и правда работает.
shell "cmd /c ping www.yandex.ru >c:\result",vbHide
Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 17.03.2005 (Чт) 14:31

SHURUP писал(а):Пробовал сравнить два фильма - ничего не вышло, выдало обибку. "R-T-E 14: Out of string space"


А нефиг весь фильм (точнее два) пытаться сразу в память запихнуть!
Кусочками сравнивай.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сообщение dimix » 17.03.2005 (Чт) 14:36

Andrey Fedorov писал(а):А нефиг весь фильм (точнее два) пытаться сразу в память запихнуть!
Кусочками сравнивай.

Дык, об этом и речь - как правильно кусочками сделать?

2 Ennor & alibek: а ежели все-таки на VB (предполагается, что будут сравниваться файлы метров по 5 и отличия будут проявляться не позднее первого метра).

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 15:26

Тебе нужно просто сравнить, одинаковы они или нет? Или нужно найти отличия и совпадения (если есть)?
Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 17.03.2005 (Чт) 15:47

Ennor писал(а):Это программа File Compare из состава операционной системы. Сомневаюсь, что получится на VB написать что-то более быстрое, чем она.


Зря сомневаешься, вообще-то.
Откомпили приведенный код в Native-code (предварительно заменив в нем имена файлов на свои) и сравни его быстродействие с тем-же fc.exe.

Код: Выделить всё
Public Sub Main()
    Dim t As Double, b As Boolean
   
    t = Timer
    b = CompFiles("C:\Temp\C1.exe", "C:\Temp\C2.exe")
    MsgBox b & "  Time = " & Format$(Timer - t, "0.0000") & ""
End Sub

Public Function CompFiles(sFile1 As String, sFile2 As String) As Boolean
    Const iStep As Long = 32768
    Dim iHFile1 As String, iHFile2 As String
    Dim m1() As Byte, m2() As Byte, k As Long, j As Long, i As Long
   
    j = iStep - 1
    ReDim m1(j): ReDim m2(j)
    On Error GoTo Err_
    iHFile1 = FreeFile
    Open sFile1 For Binary Access Read As #iHFile1
    iHFile2 = FreeFile
    Open sFile2 For Binary Access Read As #iHFile2
    k = LOF(iHFile1)
    If k = LOF(iHFile2) Then
        Do While k > 0
            j = IIf(k > iStep, iStep, k)
            Get #iHFile1, , m1
            Get #iHFile2, , m2
            For i = 0 To j - 1
                If m1(i) <> m2(i) Then
                    Exit For
                End If
            Next
            If i < j Then Exit Do
            k = k - iStep
        Loop
        CompFiles = (k <= 0)
    End If

Err_:
    If Err.Number Then MsgBox Err.Description
    On Error Resume Next
    If iHFile1 Then Close #iHFile1
    If iHFile2 Then Close #iHFile2
End Function
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 17.03.2005 (Чт) 15:53

dimix писал(а):Дык, об этом и речь - как правильно кусочками сделать?


Я уже набросал код - можешь сравнивать свои фильмы...

dimix писал(а):а ежели все-таки на VB (предполагается, что будут сравниваться файлы метров по 5 и отличия будут проявляться не позднее первого метра).


Я сравниваю весь файл, а если отличия достаточно проверять только в его начале, то добавить в функцию параметр, указывающий сколько байт надо проверять - это уже сам сделаешь, оно несложно...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 17.03.2005 (Чт) 15:57

Andrey Fedorov писал(а):Я сравниваю весь файл, а если отличия достаточно проверять только в его начале, то добавить в функцию параметр, указывающий сколько байт надо проверять - это уже сам сделаешь, оно несложно...


А впрочем держи, я добавил этот параметр:

Код: Выделить всё
Public Function CompFiles(sFile1 As String, sFile2 As String, Optional iLenCmp As Long = 0) As Boolean
    Const iStep As Long = 32768
    Dim iHFile1 As String, iHFile2 As String
    Dim m1() As Byte, m2() As Byte, k As Long, j As Long, i As Long
   
    j = iStep - 1
    ReDim m1(j): ReDim m2(j)
    On Error GoTo Err_
    iHFile1 = FreeFile
    Open sFile1 For Binary Access Read As #iHFile1
    iHFile2 = FreeFile
    Open sFile2 For Binary Access Read As #iHFile2
    k = LOF(iHFile1)
    If k = LOF(iHFile2) Then
        If iLenCmp > 0 And iLenCmp < k Then k = iLenCmp
        Do While k > 0
            j = IIf(k > iStep, iStep, k)
            Get #iHFile1, , m1
            Get #iHFile2, , m2
            For i = 0 To j - 1
                If m1(i) <> m2(i) Then
                    Exit For
                End If
            Next
            If i < j Then Exit Do
            k = k - iStep
        Loop
        CompFiles = (k <= 0)
    End If

Err_:
    If Err.Number Then MsgBox Err.Description
    On Error Resume Next
    If iHFile1 Then Close #iHFile1
    If iHFile2 Then Close #iHFile2
End Function
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 16:17

Andrey Fedorov писал(а):
Ennor писал(а):Это программа File Compare из состава операционной системы. Сомневаюсь, что получится на VB написать что-то более быстрое, чем она.


Зря сомневаешься, вообще-то.
Откомпили приведенный код в Native-code (предварительно заменив в нем имена файлов на свои) и сравни его быстродействие с тем-же fc.exe.
[/syntax]

Некорректно сравнивать. FC умеет не только сравнивать два файла на предмет того, одинаковы они или нет. Она показывает отличия, а это куда сложнее.
Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 17.03.2005 (Чт) 16:30

alibek писал(а):Некорректно сравнивать. FC умеет не только сравнивать два файла на предмет того, одинаковы они или нет. Она показывает отличия, а это куда сложнее.


Сравнение достаточно корректное.

Посмотри код - я и так сравниваю побайтно два массива. Достаточно чуть изменить код чтобы не прерывать проверку при несовпадении, а выводить несовпадающие элементы и получим ту возможность FC о которой ты пишешь. Так что по сложности/скорости это практически то-же самое. Но у нас и не ставилось такой задачи - требовалась элементарная проверка на совпадение. Она и сделана.

Кстати, у себя я проверял на файлах в 65 мег с несовпадающим последним байтом, так что файл сравнивался весь...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 16:38

Ты видимо не пользовался FC :)
Я не вижу в твоей программе кода, который бы вновь находил общие фрагменты после того, как отобразит отличия.
Lasciate ogni speranza, voi ch'entrate.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 17.03.2005 (Чт) 16:41

Файл1
Код: Выделить всё
test1
test2
test3
test4
test5
test6
test7

test2-1
test2-2
test2-3
test2-4
test2-5


Файл2
Код: Выделить всё
test1
test2
test3
test4
test6
test7

test2-1
test2-2
test2-3

test2-4
test2-5


Результаты сравнения:
Код: Выделить всё
***** test1
test4
test5
test6
***** TEST2
test4
test6
*****

***** test1
test2-3
test2-4
***** TEST2
test2-3

test2-4
*****

Lasciate ogni speranza, voi ch'entrate.

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 17.03.2005 (Чт) 16:43

alibek писал(а):Ты видимо не пользовался FC :)
Я не вижу в твоей программе кода, который бы вновь находил общие фрагменты после того, как отобразит отличия.


Ты ведь не хочешь сказать что FC с ключиком /b находит общие фрагменты? Я ведь имел в виду бинарное сравнение. Другое по условию и не нужно.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

dimix
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 174
Зарегистрирован: 08.02.2005 (Вт) 22:47

Сообщение dimix » 17.03.2005 (Чт) 20:49

Так! Ну-ка не катить бочку на Andrey Fedorov!!!
Его пример на данный момент признан лучшим с точки зрения соответствия поставленной задаче, а также награждается призом моих симпатий :)
Ведь я хотел именно на VB и именно узнавать сам факт - отличаются или нет; чем отличаются - не имеет значения.

Все остальные получают искреннюю признательность и утешительные призы - мою благодарность за помощь! :)

xolod
Гуру
Гуру
 
Сообщения: 1162
Зарегистрирован: 15.01.2004 (Чт) 0:42
Откуда: Moscow

Сообщение xolod » 17.03.2005 (Чт) 23:35

[ехидно так..]
Ну и конечно, уже после закрытия всех вопросов внесу лежку дегтя.
Любой здравомыслящий C'шник для определения идентичности файла посчитает контрольную сумму CRC32 и будет спать спокойно. Ведь это и быстрее в разы и куда удобнее.

Constant ERROR_SUCCESS deprecated. I'm so happy.
Программирование и дизайн – http://www.macrointellect.ru

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 139

    TopList