|
Antwort |
Registriert seit: 2. Mär 2004 Ort: Würzburg 730 Beiträge Delphi 2006 Personal |
#1
Hi,
also eigentlich wollte ich nur mal wieder nen bisschen mit Callback-Routinen und so Zeugs was rumprobieren und da kam dann folgendes dabei raus.. Die Funktion GetFileAsHex öffnet eine Datei, übergibt ihren Inhalt im Hexadezimal-Format an einen TStrings-Parameter und liefert ein Boolsches Ergebnis, ob alles funktioniert hat. Über eine Callback-Routine erfährt man den Fortschritt der Aktion und man kann diese darüber auch abbrechen. Tja, sonst alles soweit auch alles erklärt sein, kommentiert ist's auch... Ein Anwendungsbeispiel folgt weiter unten.
Delphi-Quellcode:
uses
System, Classes, Windows, SysUtils; Type TFileToHexCallback= PROCEDURE(const aPercent:Byte; var Cancel:Boolean); function GetFileAsHex(const aFileName : String; SL : TStrings; Formatted : Boolean = TRUE; aCallback : TFileToHexCallback = NIL) : Boolean; { **************************************************************************** } { * ---------------------- GetFileAsHex ------------------------- * } { **************************************************************************** } { * GetFileAsHex opens a file from given 'aFileName' * } { * The binary HEX-code of the file is written into 'SL', 16 bytes per line * } { * If 'Formatted' is set, a blank is inserted after each byte and one more * } { * between the two words in each line. [optional parameter] * } { * If aCallback is given you are able to show the progress (in percent) * } { * and to cancel it [optional parameter] * } { * ------------------------------------------------------------------------ * } { * GetFileAsHex returns TRUE if everything worked fine, otherwise FALSE. * } { * Reasons for failing: SL=NIL, File doesn't exist, Abort, Errors/Exceptions* } { * ------------------------------------------------------------------------ * } { * Definition of the Callback-Routine: * } { * TFileToHexCallback= PROCEDURE(const aPercent:Byte; var Cancel:Boolean); * } { * ------------------------------------------------------------------------ * } { * Note: "Huge-Strings" must be set! (*$H+*) * } { * ------------------------------------------------------------------------ * } { * At the moment the number of bytes per line, the kind of formatting and * } { * the frequency of calling the 'aCallback'-routine are completely fixed * } { * but you are free to change them (and everything else as well ;-) * } { **************************************************************************** } { * Author: Steve, delphipraxis.net * Version: v1.0 [07/2005] * } { **************************************************************************** } var F : TFileStream; hex, erg : string; ii : LongWord; {4Byte} value, max : Int64; {8Byte} bVal, nn : Byte; {1Byte} ch : PChar; {1Byte} cancel : Boolean; {1Byte} const SPACE : Char = ' '; ERROR_MSG : PAnsiChar = 'Error'; INFO_MSG : PAnsiChar = 'Information'; ABORT_MSG : PAnsiChar = 'Aborted!'; // --------- Internal procedure ---------------------------------------------- function DoCallback : Boolean; begin Result := TRUE; if Assigned(aCallback) then begin aCallback(Trunc(F.Position/max*100), Cancel); Result := not Cancel; if Cancel then MessageBox(0, ABORT_MSG, INFO_MSG, MB_OK or MB_ICONWARNING); end; end; // --- DoCallback (Internal procedure) ---------------------------------- begin // ---------------- // Checking for errors and stuff... // ---------------- Cancel := FALSE; Result := FALSE; if not Assigned(SL) then Exit; SL.Clear; if not FileExists(aFileName) then Result := FALSE else // ---------------- // Okay, let's go.... // ---------------- try try F := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyNone); max := F.Size; // ------ First, we read blocks of 2*8 bytes: ---------------------------- while F.Position+2*SizeOf(Value) <= Max do begin Erg := ''; // 3 Characters (0-F,0-F,Space) * 2 "blocks" * Count of Bytes + 1 Space if Formatted then SetLength(Erg, 3*2*SizeOf(Value)+1) else SetLength(Erg, 2*2*SizeOf(Value)); ch := @Erg[1]; Dec(ch); // ========= READ AND CONVERT NOW ====================================== for nn:=1 to 2 do begin F.Read(Value, SizeOf(Value)); for ii:=0 to SizeOf(Value)-1 do begin hex := IntToHex(Byte(Value shr (ii*8)), 2); Inc(ch); ch^ := hex[1]; Inc(ch); ch^ := hex[2]; if Formatted then begin Inc(ch); ch^ := SPACE; end; end; // 8 Bytes read -> next "block" if (nn=1) then begin if Formatted then begin Inc(ch); ch^ := SPACE end; end else SL.Add(Erg); end; // Time for a callback... if not DoCallback then Break; end; Erg := ''; // ------ The rest of the file we get single bytes: ---------------------- if not Cancel then begin // Initialize variables ERG and CH if Formatted then SetLength(Erg, 3*16+1) else SetLength(Erg, 2*16); ch := @Erg[1]; Dec(ch); for nn:=1 to Length(Erg) do begin Inc(ch); ch^:= #0; end; ch := @Erg[1]; Dec(ch); while F.Position+SizeOf(bVal) <= Max do begin // 3 Characters (0-F,0-F,Space) * 2 "blocks" à 8 Bytes + 1 Space // ========= READ AND CONVERT NOW ==================================== F.Read(bVal, SizeOf(bVal)); hex := IntToHex(bVal, SizeOf(bVal)*2); for ii:=1 to SizeOf(bVal)*2 do begin Inc(ch); ch^ := hex[ii]; end; if Formatted then begin Inc(ch); ch^ := SPACE; if F.Position mod 8 = 0 then begin Inc(ch); ch^ := SPACE; end; end; // Time for a callback... if not DoCallback then Break; end; if Erg<>'' then SL.Add(Erg); end; { IF NOT Cancel } // We're done :-) if Assigned(aCallback) then aCallback(100, Cancel); Result := TRUE; // ---------------- // Exception-Handling // ---------------- except on E:Exception do begin MessageBox(0, PChar(E.Message), ERROR_MSG, MB_OK or MB_ICONERROR); result := false; end; end; // ---------------- // Clean up again... // ---------------- finally FreeAndNil(F); end; end; { GetFileAsHex } So, nun mal ein Anwendungsbeispiel:
Delphi-Quellcode:
type
TForm1 = class(TForm) ... OpenDialog1 : TOpenDialog; Memo1 : TMemo; ProgressBar1 : TProgressBar; Button3 : TButton; public DoCancel : Boolean; end; ... // Bei Buttonklick Abbruchbedingung setzen procedure TForm1.Button3Click(Sender: TObject); begin DoCancel := TRUE; end; // Die Callback-Routine - Keine Methode, da in Deklaration kein 'of object' PROCEDURE Progress(const aPercent : Byte; var Cancel : Boolean); BEGIN Form1.ProgressBar1.Position := aPercent; Application.ProcessMessages; Cancel := Form1.DoCancel; END; // -- Hier nun der eigentliche Aufruf -- procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then begin DoCancel := FALSE; GetFileAsHex(OpenDialog1.FileName,memo1.Lines,TRUE,Progress); end; end; Das Ergebnis sieht dann folgendermaßen aus:
Code:
Abschließend sei noch erwähnt, dass sich das Ganze mit Sicherheit noch an zig Stellen verbessern, beschleunigen und vereinfachen lässt... also nur zu!
// Formatted=TRUE
42 4D 10 01 00 00 00 00 00 00 76 00 00 00 28 00 00 00 10 00 00 00 10 00 00 00 01 00 04 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80 00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF ... //Formatted=FALSE 424D1001000000000000760000002800 00001000000010000000010004000000 00008000000000000000000000000000 00000000000000000000000080000080 00000080800080000000800080008080 0000C0C0C000808080000000FF0000FF 000000FFFF00FF000000FF00FF00FFFF ... Gruß Stephan [edit=fkerber]Neu abgespeichert wg. Code-Highlighting. Mfg, fkerber[/edit]
Stephan B.
Wer andern eine Grube gräbt ist Bauarbeiter! Wer im Glashaus sitzt, sollte sich lieber im Dunkeln ausziehen! Außerdem dieser Satz kein Verb... |
Zitat |
Registriert seit: 2. Mär 2004 Ort: Würzburg 730 Beiträge Delphi 2006 Personal |
#2
Jo das wäre eigentlich geschickter...
Das sähe dann in etwa so aus:
Delphi-Quellcode:
Die Implementierung:
THexProgressEvent = procedure (const aPercent : Byte; var Cancel : Boolean) of object;
THexLoader = class(TObject) private FOnProgress : THexProgressEvent; procedure SetOnProgress(const Value: THexProgressEvent); public function LoadFileAsHex(const aFileName : string; SL : TStrings; Formatted : Boolean = TRUE) : Boolean; published property OnProgress : THexProgressEvent read FOnProgress write SetOnProgress; end;
Delphi-Quellcode:
Die Anwendung könnte dann so aussehen:
function THexLoader.LoadFileAsHex(const aFileName : string;
SL : TStrings; Formatted : Boolean = TRUE) : Boolean; { **************************************************************************** } { * ---------------------- LoadFileAsHex ------------------------- * } { **************************************************************************** } { * LoadFileAsHex opens a file from given 'aFileName' * } { * The binary HEX-code of the file is written into 'SL', 16 bytes per line * } { * If 'Formatted' is set, a blank is inserted after each byte and one more * } { * between the two words in each line. [optional parameter] * } { * ------------------------------------------------------------------------ * } { * LoadFileAsHex returns TRUE if everything worked fine, otherwise FALSE. * } { * Reasons for failing: SL=NIL, File doesn't exist, Abort, Errors/Exceptions* } { * ------------------------------------------------------------------------ * } { * Note: "Huge-Strings" must be set! (*$H+*) * } { * ------------------------------------------------------------------------ * } { * At the moment the number of bytes per line, the kind of formatting and * } { * the frequency of calling the 'aCallback'-routine are completely fixed * } { * but you are free to change them (and everything else as well ;-) * } { **************************************************************************** } { * Author: Steve, delphipraxis.net * Version: v1.1 [07/2005] * } { **************************************************************************** } var F : TFileStream; hex, erg : string; ii : LongWord; {4Byte} value, max : Int64; {8Byte} bVal, nn : Byte; {1Byte} ch : PChar; {1Byte} cancel : Boolean; {1Byte} const SPACE : Char = ' '; ERROR_MSG : PAnsiChar = 'Error'; INFO_MSG : PAnsiChar = 'Information'; ABORT_MSG : PAnsiChar = 'Aborted!'; // --------- Internal procedure ---------------------------------------------- function DoEvent : Boolean; begin Result := TRUE; if Assigned(FOnProgress) then begin FOnProgress(Trunc(F.Position/max*100), Cancel); Result := not Cancel; if Cancel then MessageBox(0, ABORT_MSG, INFO_MSG, MB_OK or MB_ICONWARNING); end; end; // --- DoEvent (Internal procedure) ---------------------------------- begin // ---------------- // Checking for errors and stuff... // ---------------- Cancel := FALSE; Result := FALSE; if not Assigned(SL) then Exit; SL.Clear; if not FileExists(aFileName) then Result := FALSE else // ---------------- // Okay, let's go.... // ---------------- try try F := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyNone); max := F.Size; // ------ First, we read blocks of 2*8 bytes: ---------------------------- while F.Position+2*SizeOf(Value) <= Max do begin Erg := ''; // 3 Characters (0-F,0-F,Space) * 2 "blocks" * Count of Bytes + 1 Space if Formatted then SetLength(Erg, 3*2*SizeOf(Value)+1) else SetLength(Erg, 2*2*SizeOf(Value)); ch := @Erg[1]; Dec(ch); // ========= READ AND CONVERT NOW ====================================== for nn:=1 to 2 do begin F.Read(Value, SizeOf(Value)); for ii:=0 to SizeOf(Value)-1 do begin hex := IntToHex(Byte(Value shr (ii*8)), 2); Inc(ch); ch^ := hex[1]; Inc(ch); ch^ := hex[2]; if Formatted then begin Inc(ch); ch^ := SPACE; end; end; // 8 Bytes read -> next "block" if (nn=1) then begin if Formatted then begin Inc(ch); ch^ := SPACE end; end else SL.Add(Erg); end; // Time for executing an event... if not DoEvent then Break; end; Erg := ''; // ------ The rest of the file we get single bytes: ---------------------- if not Cancel then begin // Initialize variables ERG and CH if Formatted then SetLength(Erg, 3*16+1) else SetLength(Erg, 2*16); ch := @Erg[1]; Dec(ch); for nn:=1 to Length(Erg) do begin Inc(ch); ch^:= #0; end; ch := @Erg[1]; Dec(ch); while F.Position+SizeOf(bVal) <= Max do begin // 3 Characters (0-F,0-F,Space) * 2 "blocks" à 8 Bytes + 1 Space // ========= READ AND CONVERT NOW ==================================== F.Read(bVal, SizeOf(bVal)); hex := IntToHex(bVal, SizeOf(bVal)*2); for ii:=1 to SizeOf(bVal)*2 do begin Inc(ch); ch^ := hex[ii]; end; if Formatted then begin Inc(ch); ch^ := SPACE; if F.Position mod 8 = 0 then begin Inc(ch); ch^ := SPACE; end; end; // Time for executing an event... if not DoEvent then Break; end; if Erg<>'' then SL.Add(Erg); end; { IF NOT Cancel } // We're done :-) if Assigned(FOnProgress) then FOnProgress(100, Cancel); Result := TRUE; // ---------------- // Exception-Handling // ---------------- except on E:Exception do begin MessageBox(0, PChar(E.Message), ERROR_MSG, MB_OK or MB_ICONERROR); result := false; end; end; // ---------------- // Clean up again... // ---------------- finally FreeAndNil(F); end; end; { THexLoader.LoadFileAsHex } procedure THexer.SetOnProgress(const Value: THexProgressEvent); begin FOnProgress := Value; end;
Delphi-Quellcode:
Aus der Callback-Routine wird also kurz gesagt einfach ein Event, mehr ändert sich eigentlich nicht.
procedure TForm1.Progress(const aPercent : Byte; var Cancel : Boolean);
begin ProgressBar1.Position := aPercent; Cancel := DoCancel; Application.ProcessMessages; end; procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog1.Execute then begin DoCancel := FALSE; with THexLoader.Create do begin OnProgress := Progress; LoadFileAsHex(OpenDialog1.FileName, Memo1.Lines, False); Free; end; end; end; Gruß Stephan [edit]Tippfehler...[/edit] [edit=fkerber]Neu abgespeichert wg. Code-Highlighting. Mfg, fkerber[/edit]
Stephan B.
Wer andern eine Grube gräbt ist Bauarbeiter! Wer im Glashaus sitzt, sollte sich lieber im Dunkeln ausziehen! Außerdem dieser Satz kein Verb... |
Zitat |
Registriert seit: 29. Mai 2002 37.621 Beiträge Delphi 2006 Professional |
#3
Warum ist dein Code eigentlich so lang?
http://www.michael-puff.de/Developer...HexLoader.html [edit=fkerber]Link korrigiert. Mfg, fkerber[/edit]
Michael
Ein Teil meines Codes würde euch verunsichern. |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |