Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - TMemoryStream ändert Inhalt beim Speichern


mexx - Fr 13.04.07 16:02
Titel: TMemoryStream ändert Inhalt beim Speichern
Ich verwende die FastReport-Komponenten und speichere einen Report wie folgt in einen Blob-Feld einer FireBird-Datenbank.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
...
var MemStream: TStream;
begin
...
 MemStream := TMemoryStream.Create;
 MemStream.Position := 0;
 FastReport.Report.SaveToStream(MemStream);
 
 QueryInsertReport.ParamByName('FastReport').LoadFromStream(MemStream,ftBlob);
...
end;


Die Verfahrensweise habe ich von einer Anleitung für den FastReport. Mit einer ShowMessage auf das Value des Parameters von 'QueryInsertReport.ParamByName('FastReport')' sehe ich, dass Einträge im Report wie ü,ä und ö verändert wurden. Die Umlaute sind nun ##. Speichere ich den Report als Datei passiert das nicht. Speicher ich andere Daten mit Umlauten in der Datenbank, verändern sich die Daten auch nicht.

Es muss also irgendwas beim 'SaveToStream(MemStream)' oder beim 'ParamByName('FastReport').LoadFromStream(MemStream,ftBlob)' mit dem Stream passieren. Aber wie finde ich das raus und welche Möglichkeiten habe ich, das Speichern des Reports als Blob in der Datanbank anders zu machen?

mexx


HelgeLange - Fr 13.04.07 16:22

ist es vielelicht die Datenbank, die einen Zeichensatz benutzt, der das automatisch ändert ? Ich glaube, ich hatte mal sowas bei Firebird, seitdem nehme ich immer CharSet NONE :)


mexx - Fr 13.04.07 16:31
Titel: Re: TMemoryStream ändert Inhalt beim Speichern
user profile iconmexx hat folgendes geschrieben:
Speicher ich andere Daten mit Umlauten in der Datenbank, verändern sich die Daten auch nicht.


Ich bin dankbar für jeden Tipp. Aber das kann ich ausschließen.


Narses - Fr 13.04.07 16:55

Moin!

Nur zur Sicherheit: vor dem .LoadFromStream setzt du .Position := 0, oder? ;)

cu
Narses


HelgeLange - Fr 13.04.07 17:26

und man kann auch für blob-feld-definitionen ein charset setzen, welches anders ist als das globale der datenbank. Es gibt auch verschiedene typen von Blobfeldern bei Firebird zum Bsp


mexx - Mo 16.04.07 07:59

@Narses: Ja, aber das nimmt keinen Einfluss. Da das BlobFeld in der Datenbank SubType 1 ist, kann ich mit einen Datanbank-Editor darauf zugreifen und sehe, dass bereits dort die Umlaute keiner Umlaute mehr sind.

@HelgeLange: Ganz wichtig zu wissen ist, dass es sich bei der Query NICHT um die Datenmenge aus der Datenbank handelt, sondern um eine Ergebnismenge einer Datenbankprocedure. Deswegen ist es nicht möglich das Blob als Feldinhalt, als FieldByName('Blob').Value := BlobStream, zu übergeben. Ich muss es als Parameter einer Query übergeben. Bei einen Parameter kann ich jedoch nur den Typ deklarieren. Kein Charset! Der BlobTyp in der Datenbank ist SubType 1. Also Text.

Ich bin mir sicher, dass der Fehler in der Übergabe des Reports an den Parameter liegt, aber welche Möglichkeiten habe ich, es anders zu machen. Ich kenne nur diese Syntacs.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
... 
var MemStream: TStream; 
begin 
... 
 MemStream := TMemoryStream.Create; 
 MemStream.Position := 0
 FastReport.Report.SaveToStream(MemStream); //entweder passiert hier ein Fehler mit dem Blobinhalten
  
 QueryInsertReport.ParamByName('FastReport').LoadFromStream(MemStream,ftBlob); //oder hier werden die Inhalte verändert 
... 
end;


alzaimar - Mo 16.04.07 08:17

Von Firebird und den Blobs habe ich keine Ahnung: Aber bist du dir sicher, das der Report im ASCII-Format im Stream gespeichert wird? Ich gehe mal davon aus, das da der Haken ist: FastReport erzeugt einen Byte-Stream (also nix 'TEXT') und der soll dann in einem TEXT-Blob abgelegt werden. Da wird FB mit Sicherheit konvertieren und -rumms- sind die Daten futsch. Ich kenn das von MSSQL jedenfalls so.

Falls Du keine andere Möglichkeit hast, dann konvertiere den Stream in eine HEX-Zahlenfolge und speichere diesen 'Text' dann ab. Dann sind die Reports zwar doppelt so groß, aber was solls.


mexx - Mo 16.04.07 08:20

user profile iconalzaimar hat folgendes geschrieben:

Falls Du keine andere Möglichkeit hast, dann konvertiere den Stream in eine HEX-Zahlenfolge und speichere diesen 'Text' dann ab. Dann sind die Reports zwar doppelt so groß, aber was solls.


Das klingt vielversprechend. Kannst Du mir bitte zeigen wie das geht oder mir ein Link mit Infos geben? Ich weiß nicht, wie man ein Stream in HEX wandelt!


alzaimar - Mo 16.04.07 08:50

Such mal nach HexToBin und BinToHex in der Classes-Unit.

Generell sollte es so klappen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Function FastReportStreamToHexString (sFastReport : TMemoryStream) : String;
Var
  p : PChar;

Begin
  setLength (Result, 2*sFastReport .Size);         // 1 Byte => 2 Char im HEX-Format.
  P := PChar (sFastReport Memory);                 // Memory zeigt auf das 1.Zeichen des FastReport-Streams
  BinToHex (P, PChar (Result), sFRT.Size); 
End;

Procedure StringToFastReportStream (aString : String; sFastReport : TMemoryStream);
Var
  p : PChar;

Begin
  sFastReport.Size := Length (aString) div 2;      // 2 HEX-Char => 1 Byte im Stream
  P := PChar (sFastReport Memory);             
  HexToBin (PChar (aString), P, Length (aString)); // Nun zurück konvertieren
End;

Ist ungetestet, sollte aber funktionieren.


mexx - Mo 16.04.07 09:18

Ich hab es wie folgt.

Lesen

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
...
var BlobStream: TMemoryStream;
...
 BlobStream := TMemoryStream.Create;
 BlobStream := CreateBlobStream(FieldByName('FAST_REPORT'),bmRead);
 BlobStream.Position := 0;
 MainFstRpt.LoadFromStream(BlobStream);
 BlobStream.Free;
...

Fehler: [Fehler] FstRptModul.pas(325): Inkompatible Typen: 'TMemoryStream' und 'TStream'



Schreiben

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
function TFstReportModul.MainDesignerSaveReport(Report: TfrxReport;
  SaveAs: Boolean): Boolean;

  Function FastReportStreamToHexString (sFastReport : TMemoryStream) : String;
   Var
     p : PChar;
   Begin
     setLength (Result, 2*sFastReport .Size);    
     P := PChar (sFastReport);               
     BinToHex (P, PChar (Result), sFastReport.Size);
   End;

...
begin
...
  Blobstream := TMemoryStream.Create;
  MainFstRpt.Report.SaveToStream(BlobStream);
  ParamByName('FastReport').Value := FastReportStreamToHexString(BlobStream);
  BlobStream.Free;
...


Den Fehler verstehe ich jedoch nicht.


alzaimar - Mo 16.04.07 09:27

Zu 1. Createblobstream erzeugt einen TBlobStream. Den müsstest Du in einen TMemoryStream kopieren, oder die StreamToString-Routine umschreiben, das der Hex-Code immer byteweise erzeugt wird. (Stichwort: 'TStream.CopyFrom')

Zu 2. Nun ist das Resultat der StreamToString-Funktion ein 'String'. Dein Feld ist aber ein BLOB.... (Stichwort: TStringStream)


mexx - Mo 16.04.07 09:42

Ehrlich gesagt, ich verstehs nicht.


mexx - Mo 16.04.07 10:00

Da der Report eine XML-File ist, gehe ich davon aus, dass der BlobStream nichts weiter als diese XML-File ist. Kein Binärcode. Sondern der reine String. Liege ich das falsch?

Ein Blobfeld kann doch alle möglichen Inhalte tragen. Da spielt es doch keine Rolle, was ich dem Parameter gebe.


alzaimar - Mo 16.04.07 10:31

Oh, XML? Echt? Na dann sollte es funktionieren. Speichere doch mal das XML, so wie es von FR kommt und dann, wenn Du es wieder ausliest. Wo sind die Unterschiede? Besorg Dir 'Beyond Compare' oder WinDiff http://en.wikipedia.org/wiki/WinDiff.


mexx - Mo 16.04.07 11:39

Können wir bitte nochmal über die Procedure StringToFastReportStream reden?

Ich muss der Procedure ja ein MemoryStream geben(HEX), diesen in Binär umwandeln und dann wieder in ein Stream zurück wandeln, weil ich einen Stream in den Reportdesigner laden muss.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  function StringToFastReportStream (aString: String; sFastReport : TMemoryStream): TMemoryStream;
   Var
     p : PChar;
   Begin
    sFastReport.Size := Length (aString) div 2;      
    P := PChar (sFastReport);
    HexToBin (PChar (aString), P, Length (aString)); // Hexcode in Bincode

 //Hier müsste nun die Variable P in ein Stream gewandelt werden aber wie?

 Result := ???
   End;


mexx - Mo 16.04.07 11:41


Delphi-Quelltext
1:
Result.Write(P,Length(P));                    


:?: :D :?:


alzaimar - Mo 16.04.07 11:57

Nee, das brauchst Du alles nicht, wenn dein Stream sowieso schon reinen ASCII (also XML) beinhaltet.

Dann tut es auch ein TStringStream.

Schreiben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
Var
  S : TStringStream;

Begin
  S:= TStringStream.Create('');
  Try
    Report.SaveToStream (S);
    myQuery.ParamByName('FastReport').Value := S.DataString;
  Finally
    S.Free;
  End;
End;


Und wieder lesen:

Sei 'ReportString' der String aus der DB, der den FastReport enthält...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
Var
  S : TStringStream;

Begin
  S := TStringStream.Create (ReportString);
  Try
    Report.LoadFromStream (S);
  Finally
    S.Free;
  End
End;


Klappt denn jetzt alles?


mexx - Mo 16.04.07 13:03

Leider nein! Der Umlaut wird immernoch falsch in die Datenbank geschrieben. Ich möchte nochmal auf das Verfahren mit der Umwandlung in HEX eingehen. Hier mal der aktuelle Code.

Schreiben

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
...
 var BlobStream: TMemoryStream;
...
function TFstReportModul.MainDesignerSaveReport(Report: TfrxReport;SaveAs: Boolean): Boolean;

  Function FastReportStreamToHexString (sFastReport : TMemoryStream) : String;
   var
     p : PChar;
   begin
     setLength (Result, 2 * sFastReport .Size);         
     P := PChar (sFastReport);
     BinToHex (P, PChar (Result), sFastReport.Size);
   end;
...
begin
...
 Blobstream := TMemoryStream.Create;
 BlobStream.Position := 0;
 MainFstRpt.Report.SaveToStream(BlobStream);
 ParamByName('FastReport').Value := FastReportStreamToHexString(BlobStream);
 BlobStream.Free;
...

FUNKTIONIERT!!
Ergebnis:24FA41006810F9037906000079060000002000001E00000024FA410000000000000000000000000000
0000001C0000001E000000010000000C00000044425465787441656E646572000000002A000000E0FC420000000
000088D4900642A8501F88E840100000000080000FF6000000000000000220000005CFE420000000000782F4...



Lesen

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
...
var LoadStream: TStream;
...
function LoadReport(ShowDialog: Boolean;AMode: TReportMode; Sprache, AReportName: String):Boolean;

  function HexStreamToBinStream (sFastReport : TStream): TStream;
   Var
     p : PChar;
     aString: String;
   Begin
    aString := StringOfChar(#00,sFastReport.Size);   // Stream to String
    sFastReport.Size := Length (aString) div 2;      // 2 HEX-Char => 1 Byte im Stream
    P := PChar (sFastReport);
    HexToBin (PChar (aString), P, Length (aString)); // von Hex zu Bin zurück
    Result.Write(P,Length(P));                       // String to Stream
   End;
...
 begin

  LoadStream := TStream.Create;
  LoadStream := HexStreamToBin (CreateBlobStream(FieldByName('FAST_REPORT'),bmRead));
  MainFstRpt.LoadFromStream(LoadStream);
  LoadStream.Free;
...


Ich brauche als Result von HexStreamToBinStream ein Stream, weil ich ein Stream als Report laden muss.

Fehler: Zugriffsverletzung bei 'Result.Write(P,Length(P));' Warum?

Danke für Deine Hilfe!


Horst_H - Mo 16.04.07 13:21

Hallo,
Vielleicht liegt es an den Daten mit Großbuchstaben??
In der Hilfe bei HexToBin:
Zitat:
Note: The hexadecimal number must use lower-case characters; HexToBin does not recognize upper-case characters.


Oder aber einfach P dereferenzieren:

Delphi-Quelltext
1:
Result.Write(P^,Length(P));                    


Gruß Horst


alzaimar - Mo 16.04.07 13:23

Du kannst keinen TStream deklarieren, das ist ein abstrakter Vorfahr für konkrete Implementierungen, wie TMemoryStream, TFileStream, TBlobStream etc. Du musst immer einen konkreten Stream deklarieren! Nur als Parameterdeklaration kann man einen TStream verwenden (der steht für 'T<irgendwas>Stream'

Du bekommst die Daten in einem TBlobStream (via CreateBlobStream). Du kannst nun selbst die Daten 2-Byte weise auslesen (Denn 2 Byte in Hex sind 1 Byte binär) und dann Byte-für-Byte alles in einen neuen Stream schreiben, der dann die Quelle für Fastreport ist.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
Function HextStreamToByteStream (HexStream, OutStream : TStream);
Var
  p : Word;
  b : Byte;

  function HexChar(c: Byte): Byte;
  begin
    case Chr(c) of
      '0'..'9':  Result := Byte(c) - Byte('0');
      'a'..'f':  Result := (Byte(c) - Byte('a')) + 10;
      'A'..'F':  Result := (Byte(c) - Byte('A')) + 10;
    else
      Raise Exception.Create('Ungültiges HEX-Format')
    end;
  end;

  function HexByte(p: Word): Byte;
  begin
    Result := HexChar(p shr 8shl 4) + HexChar(p and $FF);
  end;

Begin
  HexStream.Seek (0, soFromBeginning);
  OutStream.Seek (0, soFromBeginning);
  While HexStream.Read (w, SizeOf (Word)) = SizeOf (Word) do Begin
    b := HexByte (w);
    OutStream.Write (b, SizeOf (b));
  End
End;


Oder mit Hilfe eines TStringStreams überführst Du den BlobStream in einen String und konvertierst ihn zurück:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Procedure StringToFastReportStream (aString : String; sFastReport : TStream);
Var
  p : PChar;

Begin
  sFastReport.Size := Length (aString) div 2;      // 2 HEX-Char => 1 Byte im Stream
  P := PChar (sFastReport Memory);             
  HexToBin (PChar (aString), P, Length (aString)); // Nun zurück konvertieren
End;
    
Function HextStreamToByteStream (HexStream, OutStream : TStream);
Var
  S : TStringStream;
  
Begin
  S := TStringStream.Create;
  S.CopyFrom (HexStream,0);
  StringToFastReportStream (S.DataString, OutStream);
End;


@Horst_H: Deshalb verwende ich gerne eine Funktion zusammen mit der Umkehrfunktion (HexToBin/BinToHex). Dann ist man gegen soetwas gefeit...

Grundsätzlich baut aber FastReport Mist, denn Umlaute haben -soweit ich weiss- in XML nix zu suchen.


mexx - Mo 16.04.07 13:58

Was ist w bei While HexStream.Read (w, SizeOf (Word)) = SizeOf (Word) do Begin?


alzaimar - Mo 16.04.07 14:03

:oops: sollte 'p' heißen


mexx - Mo 16.04.07 14:15

Ich bekomme eine Zugriffsverletzung bei 'OutStream.Seek (0, soFromBeginning);'.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
    Function HexStreamToByteStream (HexStream, OutStream: TStream):TMemoryStream;
    Var
      p : Word;
      b : Byte;

      function HexChar(c: Byte): Byte;
      begin
        case Chr(c) of
          '0'..'9':  Result := Byte(c) - Byte('0');
          'a'..'f':  Result := (Byte(c) - Byte('a')) + 10;
          'A'..'F':  Result := (Byte(c) - Byte('A')) + 10;
        else
          Raise Exception.Create('Ungültiges HEX-Format')
        end;
      end;


      function HexByte(p: Word): Byte;
      begin
        Result := (HexChar(p shr 8shl 4) + HexChar(p and $FF);
      end;


    Begin
      OutStream.Seek (0, soFromBeginning);
      HexStream.Seek (0, soFromBeginning);
      While HexStream.Read (p, SizeOf (Word)) = SizeOf (Word) do Begin
        b := HexByte (p);
        OutStream.Write (b, SizeOf (b));
      End;
      Result.CopyFrom(OutStream,0);
    End;

Aufruf:

Delphi-Quelltext
1:
2:
3:
4:
LoadStream := TMemoryStream.Create;
LoadStream := HexStreamToByteStream (CreateBlobStream(FieldByName('FAST_REPORT'),bmRead),nil);
MainFstRpt.LoadFromStream(LoadStream);
LoadStream.Free;


HelgeLange - Mo 16.04.07 14:18

erm... warum nicht den BlobTyp in der Datenbank ändern, so dass die DB nix ändert ? Meine Streams ändern sich da nämlich ned :P


mexx - Mo 16.04.07 14:20

user profile iconHelgeLange hat folgendes geschrieben:
erm... warum nicht den BlobTyp in der Datenbank ändern, so dass die DB nix ändert ? Meine Streams ändern sich da nämlich ned :P


Hatte ich schon versucht. Am Typ liegt es nicht.


alzaimar - Mo 16.04.07 14:21

mexx: Du übergibst ja auch 'nil' als OutStream :autsch:


HelgeLange - Mo 16.04.07 14:27

mal die connection-settings angeschaut ? es gibt einen Verbindngs-parameter bei firebird, wo man charset angeben kann, vielleicht hat sich da was eingeschlichen. auch mal charset setting der db selbst überprüfen.
poste doch mal die tabellen-definition


mexx - Mo 16.04.07 14:33

@HelgeLange:Der Verbindungsaufbau passiert über die BDE. Leider kann ich mich nicht von Ihr trennen. Ich kann aber durchaus andere Felder mit Umlauten belegen, was mir zeigt, dass es daran nicht liegen kann. Ich kann auch andere Blobfelder mit Umlauten belegen. Die bekommen, aber die Daten anders. Deswegen meine Theorie, dass es an dem Blobtransfer liegt.

@alzaimer:
Ich verstehe nicht, warum Du die Ausgabe als Input-Parameters der Funktion deklarierst. Ich habe das mal so gemacht, erhalte aber die Zugriffsverletzung.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
    
Function HexStreamToByteStream (HexStream: TStream):TMemoryStream;
    Var
      p : Word;
      b : Byte;
      OutStream: TStream;

      function HexChar(c: Byte): Byte;
      begin
        case Chr(c) of
          '0'..'9':  Result := Byte(c) - Byte('0');
          'a'..'f':  Result := (Byte(c) - Byte('a')) + 10;
          'A'..'F':  Result := (Byte(c) - Byte('A')) + 10;
        else
          Raise Exception.Create('Ungültiges HEX-Format')
        end;
      end;


      function HexByte(p: Word): Byte;
      begin
        Result := (HexChar(p shr 8shl 4) + HexChar(p and $FF);
      end;


    Begin
      OutStream.Seek (0, soFromBeginning);
      HexStream.Seek (0, soFromBeginning);
      While HexStream.Read (p, SizeOf (Word)) = SizeOf (Word) do Begin
        b := HexByte (p);
        OutStream.Write (b, SizeOf (b));
      End;
      Result.CopyFrom(OutStream,0);
    End;

Aufruf:

Delphi-Quelltext
1:
2:
3:
4:
          LoadStream := TMemoryStream.Create;
          LoadStream := HexStreamToByteStream (CreateBlobStream(FieldByName('FAST_REPORT'),bmRead));
          MainFstRpt.LoadFromStream(LoadStream);
          LoadStream.Free;


alzaimar - Mo 16.04.07 14:34

user profile iconmexx hat folgendes geschrieben:

@alzaimer:
Ich verstehe nicht, warum Du die Ausgabe als Input-Parameters der Funktion deklarierst. Ich habe das mal so gemacht, erhalte aber die Zugriffsverletzung.

'Function' ist falsch, es muss 'Procedure' heißen...


mexx - Mo 16.04.07 14:37

Ich brauche doch aber eine Ergebnismenge aus der Operation HexStreamToByteStream?!


alzaimar - Mo 16.04.07 14:49

In HexStream,
Out OutStream


mexx - Mo 16.04.07 14:51

Aber wie soll dann der Aufruf aussehen?


alzaimar - Mo 16.04.07 15:26


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
Procedure HexStreamToFastReportStream (HexStream, OutStream : TStream);
Begin
...
End;

Var
  S : TMemoryStream;

Begin
  S := TMemoryStream.Create; 
  HexStreamToFastReportStream (HexStreamAlsBlobStream,S);
  FastReport.LoadFromStream (S);
End;

Dich stört bestimmt, das es kein 'Var OutStream' ist. Na ja, der Stream (die Instanz) wird ja nicht verändert, sondern nur sein Inhalt. Wenn Du ein Glas Bier auffüllst, ändert sich der Inhalt, aber das Glas ist noch das Selbe.


mexx - Mo 16.04.07 15:47

Ja, ich hatte das Var vermisst. Der Aufruf geht und die While-Schleife läuft durch, aber LoadStream scheint leer zu bleiben. Es wird kein Report geladen. Die Datenbank hat aber einen HEX-Code. Wie kann ich prüfen, ob die Ergebnissmenge OutStream/LoadStream etwas enthält?

Wenn ich beim Report SaveToStream mache, in welcher Form befinden sich dann die Daten? Ist das wie ein Textfeld zu verstehen, dass den XML-Code enthält, oder ist es BIN-Code?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
    Procedure HexStreamToByteStream (HexStream, OutStream: TStream);
    Var
      p : Word;
      b : Byte;

      function HexChar(c: Byte): Byte;
      begin
        case Chr(c) of
          '0'..'9':  Result := Byte(c) - Byte('0');
          'a'..'f':  Result := (Byte(c) - Byte('a')) + 10;
          'A'..'F':  Result := (Byte(c) - Byte('A')) + 10;
        else
          Raise Exception.Create('Ungültiges HEX-Format')
        end;
      end;


      function HexByte(p: Word): Byte;
      begin
        Result := (HexChar(p shr 8shl 4) + HexChar(p and $FF);
      end;


    Begin
      OutStream.Seek (0, soFromBeginning);
      HexStream.Seek (0, soFromBeginning);
      While HexStream.Read (p, SizeOf (Word)) = SizeOf (Word) do Begin
        b := HexByte (p);
        OutStream.Write (b, SizeOf (b));
      End;
    End;

Aufruf:

Delphi-Quelltext
1:
2:
3:
4:
          LoadStream := TMemoryStream.Create;
          HexStreamToByteStream (CreateBlobStream(FieldByName('FAST_REPORT'),bmRead), LoadStream);
          MainFstRpt.LoadFromStream(LoadStream);
          LoadStream.Free;