binary comparison Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
tar

binary comparison

24 Jan 2014, 11:50

I wanted to do a simple file comare. I initially used fileread into variables , and did a straight forward comparison using = or!= to compare the filled variables. This causes the program to crash when going through a list. I used the fopen() and RawRead functions which work fine, but the comparison of the variables fails.

I do not understand why a straight forward binary comparison cannot be implemented, though fully respect the workand appreciate those that have contributed. I tried to use the :

Memory_Compare(mem1,mem2,len:=0){
return VarSetCapacity(mem2)=DllCall("ntdll\RtlCompareMemory","PTR",&mem1,"PTR",&mem2,"PTR",len?len:VarSetCapacity(mem2))

suggested by some but this does not work. I tried this with excel and a copied excel file.

I know there is a microsoft fc function and am aware people change things to hexadecimal, but I do not understand why this is so difficult to do ?
Am I missing anything ?
There is a binary rawread. Do we have to break it up byte by byte to compare the two binary strings ?
tar

Re: binary comparison  Topic is solved

24 Jan 2014, 12:03

Sorry, I mistyped things quite a lot.
I wanted to do a simple file compare.
I initially used fileread to read from 2 files into 2 variables
and did a straight forward comparison of the variables using = or != to compare the filled variables.
This does not seem to work.
My program would work through a list of pairs of files to compare.
Using the above the program to crash when going through the list.

I replaced fileread with fopen() and RawRead functions which seem to work fine for loading the file with a fixed buffersize (the program did not crash),
but the comparison of the variables fails.

I tried two excel files which had 1 cell difference.
The comparison program using = or != said that the files were the same when comparing the above.

I fully respect the work and appreciate those that have contributed to autohotkey.
I do not understand why a straight forward binary comparison cannot be implemented.

I tried to use the :

Memory_Compare(mem1,mem2,len:=0){
return VarSetCapacity(mem2)=DllCall("ntdll\RtlCompareMemory","PTR",&mem1,"PTR",&mem2,"PTR",len?len:VarSetCapacity(mem2))

suggested by some but this does not work. I tried this with an excel file and a copied excel file. The program now reports the files are different.

I know there is a microsoft fc function I could use
and am aware people change things to hexadecimal using various routines.

I do not understand why this is so difficult to do ?

Is there something I am missing ?
There is a binary raw read.
Do we have to break it up byte by byte to compare the two binary strings ?

I would appreciate your help.
I may have lost some files, not knowing that binary comparisons were not possible using = and not equal (!=) to compare binary
strings. Maybe this should be mentioned in the instructions.
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: binary comparison

24 Jan 2014, 12:32

Code: Select all

; http://www.autohotkey.com/forum/viewtopic.php?t=13385
; Text Compare v2

#SingleInstance Force
#NoTrayIcon
#NoEnv

SetBatchLines, -1
Gui, +AlwaysOnTop +LastFound
Gui, Add, Edit, w500 cGray vPath1, Enter file path #1 here.
Gui, Add, Edit, w500 cGray vPath2, Enter file path #2 here.
Gui, Add, Button, w50 gGuiSubmit, OK
Gui, Add, Button, w50 gGuiClose x+10, Cancel
Gui, Font, Bold
Gui, Add, Button, gHelp x+10, ?
Gui, Font, Norm
Gui, Add, Checkbox, x+20 vNoWhite, Ignore white space
Gui, Add, Checkbox, x+10 vMismatch, Report mismatches
Gui, Add, Checkbox, x+10 vHTML, Output in HTML
Gui, Show,,Text Compare
GuiControl, Focus, HTML
WinGet, WinID, ID
SetTimer, Edit
return
GuiClose:
ExitApp
Help:
Run,http://www.autohotkey.net/~jaco0646/Text Compare Help.html
return
GuiDropFiles:
If A_EventInfo > 2
{
 Gui, +OwnDialogs
 MsgBox,48,Text Compare, More than 2 items were dropped.
 return
}
If A_EventInfo = 2
 Loop,Parse,A_GuiEvent,`n,`r
 {
  GuiControl,Font,Path%A_Index%
  GuiControl,,Path%A_Index%,%A_LoopField%
 }
Else If (A_GuiControl="path1") OR (A_GuiControl="path2")
{
 GuiControl,Font,%A_GuiControl%
 GuiControl,,%A_GuiControl%,%A_GuiEvent%
}
return
GuiSubmit:
SetTimer, Edit, Off
Gui,Submit
Gui,Destroy
Loop,2
{
 IfNotExist,% path%A_Index%
 {
  MsgBox,16,Text Compare,% "The path does not exist:`n" path%A_Index%
  ExitApp
 }
 FileGetAttrib, attribs,% path%A_Index%
 IfInString, attribs, D
 {
  MsgBox,16,Text Compare,% "The path does not specify a file:`n" path%A_Index%
  ExitApp
 }
 StringRight,slash,Path%A_Index%,1
 If slash = \
  StringTrimRight,Path%A_Index%,Path%A_Index%,1
}
Loop
{
 match=0
 FileReadLine, line1, %Path1%, %A_Index%
 Error1 := ErrorLevel
 FileReadLine, line2, %Path2%, %A_Index%
 Error2 := ErrorLevel
 If (Error1) AND (Error2)
  break
 If NoWhite
 {
  NW1 := RegExReplace(line1,"[`t ]+")
  NW2 := RegExReplace(line2,"[`t ]+")
  If (NW1 = NW2)
   continue
  If NW1=
   Error1=1
  If NW2=
   Error2=1
 }
 Else If (line1 = line2)
  continue
 If Error1
  match+=2
 If Error2
  match++
 If file1=
 {
  FileRead, file1, %Path1%
  FileRead, file2, %Path2%
  If NoWhite
  {
   file1 := RegExReplace(file1,"[`t ]+")
   file2 := RegExReplace(file2,"[`t ]+")
  }
 }
 If Mismatch
 {
  num3=#
  num4=#
 }
 line1copy := NoWhite=1 ? NW1:line1
 line2copy := NoWhite=1 ? NW2:line2
 If Error2=0
  Loop, Parse, file1, `n,`r
   If (A_LoopField = line2copy)
   {
    match++
    num4 := A_Index
    break
   }
 If Error1=0
  Loop, Parse, file2, `n,`r
   If (A_LoopField = line1copy)
   {
    match+=2
    num3 := A_Index
    break
   }
 If (match = 3) AND !(Mismatch)
  continue
 If doc=
 {
  SplitPath,Path1,,,,NoExt1
  SplitPath,Path2,,,,NoExt2
  ext := HTML=1 ? ".html":".txt"
  doc := A_ScriptDir "\" NoExt1 "-vs-" NoExt2 ext
  If HTML
  {
   IfNotExist,%doc%
    FileAppend,
    (LTrim
     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
     <html>
     <head>
     <title>%NoExt1%-vs-%NoExt2%</title>
     </head>
     <body bgcolor="F5F5DC" text="000000">
     <font color="0000FF">
     File1 = %Path1%<BR>File2 = %Path2%
     </font>
     <font face="Lucida Console">
     <P><DL>
    )
    ,%doc%
  }
  Else FileAppend, File1 = %Path1%`r`nFile2 = %Path2%`r`n`r`n, %doc%
 }
 i++
 num := A_Index
 If (Mismatch=1) AND (match != 3)
 {
  num5 := "/" num ":" num3
  num6 := "/" num ":" num4
 }
 If HTML
 {
  Loop, 2
  {
   StringReplace, line%A_Index%, line%A_Index%, &, &amp, All
   StringReplace, line%A_Index%, line%A_Index%, <, &lt, All
   StringReplace, line%A_Index%, line%A_Index%, >, &gt, All
   StringReplace, line%A_Index%, line%A_Index%, %A_Space%, &nbsp, All
   StringReplace, line%A_Index%, line%A_Index%, %A_Tab%, &nbsp&nbsp&nbsp&nbsp&nbsp, All
  }
  If match = 0
   FileAppend,
   (LTrim
    <dt><font color="8B0000">Line %num%<BR></font>
    <dd><font color="008000">File1:</font> %line1%<BR>
        <font color="008000">File2:</font> %line2%<BR>
   )
   ,%doc%
  Else If match = 1
   FileAppend,
   (LTrim
    <dt><font color="8B0000">Line %num%%num6%<BR></font>
    <dd><font color="008000">Unique to File1:</font> %line1%<BR>
   )
   ,%doc%
  Else If match = 2
   FileAppend,
   (LTrim
    <dt><font color="8B0000">Line %num%%num5%<BR></font>
    <dd><font color="008000">Unique to File2:</font> %line2%<BR>
   )
   ,%doc%
  Else If match = 3
  {
   If (NoWhite) AND !(NW1)
    FileAppend,
   (LTrim
    <dt><font color="8B0000">Line %num%:%num3%/%num%:%num4%<BR></font>
    <dd><font color="008000">Mismatch:</font> %line2%<BR>
   )
   ,%doc%
   Else
    FileAppend,
   (LTrim
    <dt><font color="8B0000">Line %num%:%num3%/%num%:%num4%<BR></font>
    <dd><font color="008000">Mismatch:</font> %line1%<BR>
   )
   ,%doc%
  }
 }
 Else
 {
  If match = 0
   FileAppend, Line %num%`r`n%A_Tab%File1>> %line1%`r`n%A_Tab%File2>> %line2%`r`n, %doc%
  Else If match = 1
   FileAppend, Line %num%%num6%`r`n%A_Tab%Unique to File1>> %line1%`r`n, %doc%
  Else If match = 2
   FileAppend, Line %num%%num5%`r`n%A_Tab%Unique to File2>> %line2%`r`n, %doc%
  Else If match = 3
  {
   If Mismatch
   {
    If (NoWhite) AND !(NW1)
     FileAppend, Line %num%:%num3%/%num%:%num4%`r`n%A_Tab%Mismatch>> %line2%`r`n, %doc%
    Else
     FileAppend, Line %num%:%num3%/%num%:%num4%`r`n%A_Tab%Mismatch>> %line1%`r`n, %doc%
   }
   Else i--
  }
 }
}
If i
{
 If HTML
  FileAppend, </DL>%i% differences.<P><HR><DL>, %doc%
 Else FileAppend, `r`n%i% differences.`r`n`r`n, %doc%
 MsgBox,48,Text Compare
 ,%i% differences were written to the Final Report file:`n`n%NoExt1%`n-vs-`n%NoExt2%
}
Else MsgBox,64,Text Compare, These files are identical:`n`n%Path1%`n%Path2%
ExitApp
Edit:
GuiControlGet,Focus,FocusV
Loop,2
{
 GuiControlGet,Contents,,Path%A_Index%
 If Focus = Path%A_Index%
 {
  If Contents = Enter file path #%A_Index% here.
  {
   GuiControl,,Path%A_Index%
   GuiControl,Font,Path%A_Index%
  }
 }
 Else If Contents=
 {
  Gui,Font,cGray
  GuiControl,Font,Path%A_Index%
  GuiControl,,Path%A_Index%,Enter file path #%A_Index% here.
  Gui,Font
 }
}
return
User avatar
LinearSpoon
Posts: 156
Joined: 29 Sep 2013, 22:55

Re: binary comparison

24 Jan 2014, 13:00

@Guest10, that script compares text files. It might not work with binary files.
@Tar, it's hard to say what's going on without seeing your code. Try this. Note that it still might fail with two spreadsheets that appear to be the same, because there might be other data hidden in the save file, such as a timestamp. If that's the case, a binary level comparison isn't going to work.

Code: Select all

;Pass a relative or absolute filename for each file1 and file2
;Returns true if the contents of file1 = file2, or false if there are differences
FileCompare(file1, file2)
{
  FileGetSize, sFile1, %file1%
  FileGetSize, sFile2, %file2%
  if (sFile1 != sFile2)
    return 0  ;Not the same size so impossible to have the same contents
  FileRead, bFile1, *c %file1%
  FileRead, bFile2, *c %file2%
  return sFile1 = DllCall("ntdll\RtlCompareMemory", "ptr", &bFile1, "ptr", &bFile2, "ptr", sFile1)
}
Guest

Re: binary comparison

24 Jan 2014, 13:38

http://www.autohotkey.com/board/topic/4 ... entry27212

Laszlo advised a routine which seems to work based on this using another dll.
It is just sad that basic comparison is not available inhyerently in Autohotkey.
I am afraid I have become rusty and are not familiar with machine code in current day processors otherwise I would contribute.

Thanks.
tar

Re: binary comparison

24 Jan 2014, 13:46

I did try that. Unfortunately that was what I first used - a binary load and then a simple comparison.
The FileRead *c caused the program to crash.
Using varsetcapacity did not help.

Hence I had to read the file in chunks.

You can use this. Laszlo used memcmp :D .

You can stick your variables holding file data in a, and the second in b.
It seems to work.


BufferCompare(ByRef a, Byref b, n=0) ; compare buffers
{ ; a <,=,> b: Return <,=,> 0
u := VarSetCapacity(a)
v := VarSetCapacity(b)
IfLess n, 1, SetEnv n,0xffffffff ; n = 0: compare all allocated
IfLess u,%n%, SetEnv n,%u% ; use at most the capacity of a
IfLess v,%n%, SetEnv n,%v% ; use at most the capacity of b
Return DllCall("msvcrt\memcmp", "UInt", &a, "UInt", &b, "UInt", n, "CDecl Int")
}
Guest

Re: binary comparison

24 Jan 2014, 13:51

@linearspoon.

Thanks for your reply. I had not noticed your RTLcompare earlier.
I was never clear why using fileread*c, even setting the receiving variables for 100MB+ with much smaller files.
Autohotkey would just crash.

However, at least rawread reads, and other dlls compare.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 317 guests