MD5-Hash mit Callback, Fortschritt, verbleibende Zeit, usw.

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
HeX0R
Beiträge: 3054
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

Ich würde so eine Funktion aber eher mittels eines Thread machen.
Fensterevents ins Nirvana zu bomben finde ich extrem unschön.

Beispiel:

Code: Alles auswählen

#FileName = "C:\Dokumente und Einstellungen\bratwurst\Eigene Dateien\Eigene Videos\HeX0R_Poppt_Svetlana.MPG"

Structure _MD5_THREAD_PARAMETER_
	FileName.s
	BufferSize.l
	ProgressBarGadget.l
	ProgressGadget.l
	SpeedGadget.l
	TimeGadget.l
	ResultGadget.l
EndStructure


Procedure.s ByteRechner(dSize.d)
	Protected Namen.q, i.l, Result.s, R.s = "0"

	Namen = 'KMGTPEZY'
	If dSize > 0.0
		i = 56
		While dSize > 1024 And i >= 0
			dSize / 1024
			Result = Chr((Namen >> i) & $FF)
			i - 8
		Wend
		R = StrD(dSize, 2) + " " + Result + "Byte"
	EndIf

	ProcedureReturn R
EndProcedure

Procedure MD5FileFingerPrintThread(*P._MD5_THREAD_PARAMETER_)
	Protected StartTime.l = Date()
	Protected FileID.l    = ReadFile(#PB_Any, *P\FileName)
	Protected *Buffer, FingerPrint.l
	Protected Progress.f, Elapsed.l, Speed.f, Remaining.f, Refresh.l = ElapsedMilliseconds() + 200

	If FileID
		*Buffer = AllocateMemory(*P\BufferSize)
		If *Buffer
			FingerPrint = ExamineMD5Fingerprint(#PB_Any)
			If FingerPrint
				While Eof(FileID) = 0
					NextFingerprint(FingerPrint, *Buffer, ReadData(FileID, *Buffer, *P\BufferSize))
					If Refresh < ElapsedMilliseconds()
						Elapsed  = Date() - StartTime
						Progress = Loc(FileID) / Lof(FileID) * 100
						If Elapsed ; to avoid division by zero
							Speed = Round(Loc(FileID) / Elapsed, #PB_Round_Nearest)
							If Speed ; prevent division by zero
								Remaining = Round((Lof(FileID) - Loc(FileID)) / Speed, #PB_Round_Nearest)
							EndIf
						EndIf
						If *P\ProgressBarGadget <> -1
							SetGadgetState(*P\ProgressBarGadget, Int(Progress))
						EndIf
						If *P\ProgressGadget <> -1
							SetGadgetText(*P\ProgressGadget, "Entire progress: " + StrF(Progress, 1) + "%")
						EndIf
						If *P\SpeedGadget <> -1
							SetGadgetText(*P\SpeedGadget, "Speed: " + ByteRechner(Speed) + "/sec")
						EndIf
						If *P\TimeGadget <> -1
							SetGadgetText(*P\TimeGadget, FormatDate("Elapsed: %hhh%iim%sss", Elapsed) + #CRLF$ + FormatDate("Remaining: %hhh%iim%sss", Remaining))
						EndIf
						Refresh = ElapsedMilliseconds() + 200
					EndIf
				Wend
				If *P\ResultGadget
					SetGadgetText(*P\ResultGadget, "Result: " + FinishFingerprint(FingerPrint))
				EndIf
			EndIf
			FreeMemory(*Buffer)
		EndIf
		CloseFile(FileID)
	EndIf

EndProcedure

Define ThreadID.l, Param._MD5_THREAD_PARAMETER_
Param\FileName          = #FileName
Param\BufferSize        = 16384
Param\ProgressBarGadget = 0
Param\ProgressGadget    = 1
Param\SpeedGadget       = 2
Param\TimeGadget        = 3
Param\ResultGadget      = 4

If OpenWindow(0, 0, 0, 400, 200, GetFilePart(Param\FileName), #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
	ProgressBarGadget(0,  10, 30, 250,  30, 0, 100)
	TextGadget       (1,  10, 10, 250,  20, "")
	TextGadget       (2,  10, 70, 250,  20, "")
	TextGadget       (3, 100,110, 200,  50, "")
	TextGadget       (4, 100, 170, 250, 20, "")

	ThreadID = CreateThread(@MD5FileFingerPrintThread(), @Param)

	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_CloseWindow
				If IsThread(ThreadID)
					KillThread(ThreadID)
				EndIf
				Break
		EndSelect
	ForEver
EndIf
Zuletzt geändert von HeX0R am 19.03.2008 20:49, insgesamt 1-mal geändert.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Jedem das seine! :)
Ich persönlich finde, das ist ein Universalbefehl, der etwas zurückgeben soll, das kann man mit Threads nicht so einfach bewerkstelligen. Natürlich kann man die Prozedur auch als Thread aufrufen. Und Fensterevents kann jeder so handhaben, wie er möchte, dank des Callbacks stehen einem ja (fast?) alle Wege offen.

Sinn des Codes ist es ja auch, die Arbeitsweise an sich aufzuzeigen, damit andere davon lernen können. Was mann/frau draus macht, bleibt einem selbst überlassen.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Antworten