based on Kiffi's code example how to use ExamineMD5Fingerprint() I wrote a procedure with offers you the following:
- progress in percent
- elapsed time
- remaining time
- speed in byte/second (with my attached bytecalc()-procedure, you can automatically transform bytes into KB, MB, GB, ...)
- possibility to abort the operation, if callback returns a value <>0
Code: Select all
EnableExplicit
#file="D:\Dateien\CD Image.img"
Procedure.s bytecalc(byte.q, NbDecimals.l=0)
If byte < 1024
If byte < 0
ProcedureReturn "0 Byte"
EndIf
ProcedureReturn Str(byte)+" Byte"
ElseIf byte >= 1<<60
ProcedureReturn StrD(byte/1<<60, NbDecimals)+" EB"
ElseIf byte >= 1<<50
ProcedureReturn StrD(byte/1<<50, NbDecimals)+" PB"
ElseIf byte >= 1<<40
ProcedureReturn StrD(byte/1<<40, NbDecimals)+" TB"
ElseIf byte >= 1<<30
ProcedureReturn StrD(byte/1<<30, NbDecimals)+" GB"
ElseIf byte >= 1<<20
ProcedureReturn StrD(byte/1<<20, NbDecimals)+" MB"
Else
ProcedureReturn StrD(byte/1024, NbDecimals)+" KB"
EndIf
EndProcedure
Procedure myCallback(file.s, progress.l, speed.l, remainingTime.l, elapsedTime.l)
SetGadgetText(3, "Entire progress: "+Str(progress)+"%")
SetGadgetText(4, "Speed: "+bytecalc(speed)+"/sec ("+Str(speed)+" Byte/s)")
SetGadgetText(5, FormatDate("Elapsed: %hhh%iim%sss", elapsedTime)+#CRLF$+FormatDate("Remaining: %hhh%iim%sss", remainingTime))
SetGadgetState(0, Int(progress))
While WindowEvent() : Wend
ProcedureReturn 0 ; Return 0 to continue, 1 to abort
EndProcedure
Procedure.s MD5FileFingerprintCallback(file$, *callback=0, callCallbackEvery=1000, bufferSize=4096)
; Callback format: myCallback(file.s, progress.l, speed.l, remainingTime.l, elapsedTime.l)
Protected startTime.l=Date(), file.l=ReadFile(#PB_Any, file$), hash.s
If file
Protected *buffer=AllocateMemory(bufferSize)
If *buffer
Protected fingerprint=ExamineMD5Fingerprint(#PB_Any)
If fingerprint
Protected progress.l, refresh.l, elapsed.l, speed.l, remaining.l
While Not Eof(file)
NextFingerprint(fingerprint, *buffer, ReadData(file, *buffer, bufferSize))
If *callback And ElapsedMilliseconds() > refresh
If Lof(file) ; to avoid division by zero if filesize is 0 bytes
elapsed=Date()-startTime
progress=Round(Loc(file)/Lof(file)*100, #PB_Round_Nearest)
If elapsed ; to avoid division by zero
speed=Round(Loc(file)/elapsed, #PB_Round_Nearest)
If speed ; prevent division by zero
remaining=Round((Lof(file)-Loc(file))/speed, #PB_Round_Nearest)
EndIf
EndIf
EndIf
If CallFunctionFast(*callback, file$, progress, speed, remaining, elapsed)
Break
EndIf
refresh=ElapsedMilliseconds()+callCallbackEvery
EndIf
Wend
hash=FinishFingerprint(fingerprint)
EndIf
FreeMemory(*buffer)
EndIf
CloseFile(file)
EndIf
ProcedureReturn hash
EndProcedure
If OpenWindow(0, 0, 0, 400, 160, GetFilePart(#file)+" "+bytecalc(FileSize(#file), 1), #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
ProgressBarGadget(0, 10, 30, 250, 30, 0, 100)
TextGadget (3, 10, 10, 250, 20, "")
TextGadget (4, 10, 70, 250, 20, "")
TextGadget (5, 100,110, 200, 50, "")
Define md5$=MD5FileFingerprintCallback(#file, @myCallback(), 250)
MessageRequester("MD5FileFingerprintCallback()", "finished! send donations to AND51 :-P"+#CRLF$+md5$)
EndIf
File which the MD5 hash code is being examined from.
*callback
Address of the procedure/callback to be called. If *callback=0, then the whole callback-function is being disabled. The callback must have this format:
myCallback(file.s, progress.l, speed.l, remainingTime.l, elapsedTime.l)
The callback is able to abort the operation by returning a value <>0.
callCallbackEvery
Interval in milliseconds in which the callback is being called. This is useful, because if a gadget is being updated too fast, it starts flickering.
bufferSize
Size in bytes for the buffer that should be allocated. A larger buffer can improve the performance.
Returning value
The procedure returns the MD5 hash as a string or an empty string, if there was an error (file cannot be opened, memory allocation error, ...).