Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Speichern in BlobField zerschießt MemorySTream (https://www.delphipraxis.net/212693-speichern-blobfield-zerschiesst-memorystream.html)

dataspider 16. Mär 2023 11:06

Speichern in BlobField zerschießt MemorySTream
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich bin jetzt wirklich am Verzweifeln.
Ich konvertiere von WPRichText nach DevExpress RichEditControl.

Das mache ich mit einem MemoryStream.
In meinem Konverter schreibe ich zum Test den Stream in ein File. (stream.rtf)

Delphi-Quellcode:
procedure TConvertWPRichText.ParseStream(AStream: TMemoryStream);
Var
  I: Integer;
  LStream: TMemoryStream;
  LMergeField: TMergeField;
  LNewText: Ansistring;
  LNextPos: Integer;
begin
  if (MergeFields.Count = 0) then
    Exit;
  LStream := TMemoryStream.Create;
  try
    AStream.Position := 0;
    LStream.CopyFrom(AStream);
    LStream.Position := 0;
    AStream.Clear;
    AStream.CopyFrom(LStream, FMergeFields[0].Position); // bis zum ersten Feld
    for I := 0 to MergeFields.Count - 1 do
    begin
      LMergeField := FMergeFields[I];
      LNewText := LMergeField.GetNewText;
      AStream.WriteBuffer(LNewText[1], Length(LNewText)); // neues Feld
      LStream.Seek(Length(LMergeField.Text) + 1, soFromCurrent); // Ende erstes Feld
      if I = MergeFields.Count - 1 then
        AStream.CopyFrom(LStream, LStream.Size - LStream.Position)
      else
      begin
        LNextPos := MergeFields[I + 1].Position;
        AStream.CopyFrom(LStream, LNextPos - LStream.Position);
      end;
    end;
  finally
    LStream.Free;
  end;
end;
Den Inhalt des Stream schreibe ich dann in die Datenbank

Delphi-Quellcode:
procedure TFRMEdtTextDokument.LoadTextFromDB;
var
  LStream: TMemoryStream;
begin
  if IsDestroying then
    Exit;
  RichEditControl.Clear;
  if (DM.qryMain.FieldByName('DOKUMENT').IsNull) and (DM.qryMain.FieldByName('BRIEF').IsNull) then
    Exit;
  if (DM.qryMain.FieldByName('DOKUMENT').IsNull) then
  begin
    LStream := TMemoryStream.Create;
    try
      TBlobField(DM.qryMain.FieldByName('BRIEF')).SaveToStream(LStream);
      TConvertWPRichText.Convert(LStream);
      {$IFDEF DEBUG}
        LStream.SaveToFile('stream.rtf');
      {$ENDIF}
      LStream.Position := 0;
      DM.qryMain.Edit;
      TBlobField(DM.qryMain.FieldByName('DOKUMENT')).LoadFromStream(LStream);
      DM.qryMain.Post;
    finally
      LStream.Free;
    end;
  end;
  RichEditControl.LoadFromBlobField(TBlobField(DM.qryMain.FieldByName('DOKUMENT')));
end;
Auch hier schreibe ich den Stream in eine Datei.

In den Anlagen sind 2 rtf's
stream.rtf vor dem Speichern in DB
datenbankfeld.rtf - was in der Datenbank ankommt.

Wenn ich mit IBExpert die Datei stream.rft in das Feld lade, ist es OK.

Warum kommt in der DB der Müll an?

Frank

mjustin 16. Mär 2023 12:19

AW: Speichern in BlobField zerschießt MemorySTream
 
Bei der Konvertierung wird anscheinend ein Bild im Binary Format eingefügt:

{\pict\jpegblip\picw4416\pich1027\picwgoal4416\pic hgoal1027
\bin28150 ÿØÿà...

Speichern in der Datenbank mit einem Text-Encoding (ANSI, UTF-8 ...) kann dann zu Problemen führen. Speichern in ein Blob ohne Encoding/Textkonvertierung sollte funktionieren.

Alternative Idee: vielleicht kann DevExpress RichEditControl die Bilder anstatt Binär im Hex-Format ablegen. Das hat dann einen größeren Platzbedarf, besteht aber aus ASCII Daten.

Merke: die RTF Spezifikation sieht auch das Ablegen von reinen Binärdaten in der Datei vor.

Happy coding

dataspider 16. Mär 2023 13:21

AW: Speichern in BlobField zerschießt MemorySTream
 
Zitat:

Zitat von mjustin (Beitrag 1519948)
Bei der Konvertierung wird anscheinend ein Bild im Binary Format eingefügt:

{\pict\jpegblip\picw4416\pich1027\picwgoal4416\pic hgoal1027
\bin28150 ÿØÿà...

Das ist richtig, darum ist es in der DB ein Binäres Blob (Firebird) und deshalb benutze ich TMemoryStream.
Ich dachte immer, TMemoryStream kümmert sich nicht um EnCoding.

Zitat:

Zitat von mjustin (Beitrag 1519948)
Speichern in der Datenbank mit einem Text-Encoding (ANSI, UTF-8 ...) kann dann zu Problemen führen. Speichern in ein Blob ohne Encoding/Textkonvertierung sollte funktionieren.

Wie geht "Speichern in ein Blob ohne Encoding/Textkonvertierung"?
Ich habe auch in ParseStream versucht, anstatt mit AnsiString mit TBytes zu arbeiten bei Stream.WriteBuffer. Bringt auch keine Änderung.

Zitat:

Zitat von mjustin (Beitrag 1519948)
Alternative Idee: vielleicht kann DevExpress RichEditControl die Bilder anstatt Binär im Hex-Format ablegen. Das hat dann einen größeren Platzbedarf, besteht aber aus ASCII Daten.

Also DevExpress legt die Bilder nicht binär ab. WPTools macht das. Aber ob ich das beeinflussen kann, weiß ich nicht.
Wäre auch nicht die Lösung, da ich ca. 1000 Einträge konvertieren muss.
Durch meine Routine sollte das automatisch passieren. Deshalb bei 2. Feld mit anderem Namen.

Ich bin mir ziemlich sicher, dass es nur die Zeile mit WriteBuffer ist. Aber ich komme nicht weiter.

Dennoch - Vielen Dank!

Frank

himitsu 16. Mär 2023 17:30

AW: Speichern in BlobField zerschießt MemorySTream
 
Zitat:

Zitat von dataspider (Beitrag 1519953)
Ich dachte immer, TMemoryStream kümmert sich nicht um EnCoding.

Das ist Richtig, aber vielleicht LNewText oder GetNewText?

AnsiString ??
RawByteString
oder besser noch TBytes bzw. TArray<Byte>

dataspider 17. Mär 2023 11:03

AW: Speichern in BlobField zerschießt MemorySTream
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von himitsu (Beitrag 1519960)
Zitat:

Zitat von dataspider (Beitrag 1519953)
Ich dachte immer, TMemoryStream kümmert sich nicht um EnCoding.

Das ist Richtig, aber vielleicht LNewText oder GetNewText?

AnsiString ??
RawByteString
oder besser noch TBytes bzw. TArray<Byte>

Ja, ich habe jetzt LNewText als TBytes definiert und weise den string aus GetNewText über
Delphi-Quellcode:
LNewText := BytesOf(LMergeField.GetNewText);
zu.
Das sollte jetzt wohl, wenn ich euch richtig verstanden habe, die richtige Herangehensweise sein.

Ich habe mir den Feldinhalt des Blobs jetzt vor und nach dem Post in eine Datei schreiben lassen.
Delphi-Quellcode:
  LStream.Clear;
  TBlobField(DM.qryMain.FieldByName('DOKUMENT')).SaveToStream(LStream);
  LStream.SaveToFile('1.rtf');
  DM.qryMain.Post;
  LStream.Clear;
  TBlobField(DM.qryMain.FieldByName('DOKUMENT')).SaveToStream(LStream);
  LStream.SaveToFile('2.rtf');
Das Post ist also die Ursache. Und man sieht am Screenshot, dass das RTF scheinbar "verbessert" wird.
Nach dem Post fehlt schon das "ansi" (im Screenshot markiert).
Ich habe keine Ahnung, was IBObjects da macht.

Ich lade den konvertierten Stream nicht mehr ins BlobField
sondern Stream -> RichEditControl -> Stream -> BlobField.

Damit funktioniert es und das RichEditControl wandelt gleich das Bild in nicht binär um.

Ich hätte gern verstanden, was da schief läuft, aber - was solls...

Danke Happy coding
Danke himitsu

himitsu 17. Mär 2023 11:26

AW: Speichern in BlobField zerschießt MemorySTream
 
Es gibt auch ein Delphi-Referenz durchsuchenTBytesStream

Vielleicht erkennt die Komponente, wenn ANSI aussreicht und speichert damm im kleinst möglichen Format?


So lange kein Unicode/Umlaute/Sonderzeichen vorkommen, dann reicht es ja aus und wäre auch grundsätzlich egal.

dataspider 17. Mär 2023 12:33

AW: Speichern in BlobField zerschießt MemorySTream
 
Wenn man der falschen Fährte folgt und einen Tunnelblick bekommt, sollte man erst mal abschalten.
Das habe ich jetzt gemacht. War eine Stunde laufen...

Und dann war mir klar, dass das Post nicht derartige Änderungen erzeugen kann.
Also musste irgendwie etwas Anderes in das Feld geschrieben werden.
Schön versteckt im Code gab es noch ein Ereignis ausgelöst vom BeforePost des DataSet,
welches den Inhalt des RichTextEditors ins Feld geschrieben hat.

Damit war immer ein leerer RTF - "Rumpf" in der Datenbank.
:oops:

So, jetzt keine Depression bekommen, kann passieren...

Frank


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:18 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz