![]() |
Datenbank: PostgreSQL • Version: 9.4 • Zugriff über: Zeos
Formatierten Text in PostgreSQL 9 speichern
Hallo zusammen, einen schönen 4. Advent wünsche ich,
ich versuche seit längerem für eine kleine Notizenanwendung den Text der Notiz formatiert (also fett, kursiv etc.) in einer PostgreSQL-Datenbank zu speichern, erhalte jedoch beim Wiederauslesen nur Zeichensalat. Das Feld in der Datenbank ist vom Typ bytea. Wenn ich mit der Methode
Delphi-Quellcode:
den Text als Stream in der Datenbank speichere, erhalte ich
function TfrmMain.GetRTFText: string;
var FStream : TMemoryStream; begin FStream := TMemoryStream.Create; FStream.Clear; redt1.Lines.SaveToStream(FStream); Result := PChar(FStream.Memory); FStream.Free; end; Zitat:
Delphi-Quellcode:
erhalte ich nur wirren Zeichensalat.
procedure TfrmMain.SetRTFText(RichRTFText: string);
var FStream : TMemoryStream; begin FStream := TMemoryStream.Create; FStream.Clear; FStream.WriteBuffer(RichRTFText[1], Length(RichRTFText)); FStream.Position := 0; redt1.Lines.LoadFromStream(FStream); FStream.Free; end; Hat vielleicht jemand einen Tip, wo ich ansetzen kann? Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo,
das sieht aus wie unvollständiges RTF. Zeichenfolgen in der Form "\345\261\273\347\221\262\343" können da schon vorkommen, es scheint aber der Header zu fehlen. Ein bisserl was zum RTF-Format ist hier zu finden: ![]() Speichere doch bitte den Text auch einmal mit
Delphi-Quellcode:
und schau, ob Du die Datei mit 'ner Textverarbeitung öffnen kannst und sie dort vernünftig angezeigt wird.
redt1.Lines.SaveToFile('Testdatei.rtf');
Und schau bitte mal mit Notepad, Hexeditor (oder so) in die Datei und prüfe, ob die Datei der Spezifikation entspricht oder den gleichen Inhalt hat, wie der Stream. Datei und Stream müssten eigentlich mit {\rtf beginnen und mit } enden. Ist dem bei Beiden nicht so, so wird von redt1 kein (vollständiges) RTF gespeichert. Prüfe dann mal bei den Eigenschaften, ob da was zu konfigurieren ist. Eventuell fehlt hier in der Routine aber auch was:
Delphi-Quellcode:
Ansonsten helfen diehier?
function TfrmMain.GetRTFText: string;
var FStream : TMemoryStream; begin FStream := TMemoryStream.Create; FStream.Clear; redt1.Lines.SaveToStream(FStream); FStream.Position := 0; // <- fehlt das? Result := PChar(FStream.Memory); FStream.Free; end; ![]() ![]() |
AW: Formatierten Text in PostgreSQL 9 speichern
Ich würde es mal mit Datentyp
TEXT oder für kleinere Texte VARCHAR statt BYTEA versuchen. |
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo,
danke für die Antworten. Also die RTF-Datei wird einwandfrei gespeichert und hat dann auch den korrekten Inhalt. Ich habe zwischenzeitlich ein varchar-Feld für die Daten genommen. Wenn ich allerdings den Inhalt des Richedits mit GetRTFText in einen Stream umwandle, wird ein Teil der RTF-Daten abgeschnitten, was dann so aussieht: Zitat:
Delphi-Quellcode:
hat tatsächlich gefehlt, die Korrektur hat aber keine Auswirkung auf das Ergebnis.
FStream.Position := 0;
Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Hatte vor längerer Zeit mal ähnliche Probleme beim Speichern von RTF-Dateien in Firebird. Seitdem ich nun RTF-Dateien in binären Blobfeldern speichere, wird alles so ausgegeben, wie es gespeichert wurde, und zwar fehlerfrei ebenfalls mit SaveToStream und LoadFromStream. Zuvor hatte ich den Subtyp Text des Blobtypes verwendet, was zu Darstellungsfehlern nach dem Einlesen aus Blobfeld führte.
Da du ja ebenfalls ein ![]() |
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo,
eigentlich wollte ich die Daten auch binär in einem BYTEA-Feld speichern, aber dann kommt nur wirrer Zeichensalat bei raus. Wenn ich ein Varchar-Feld nehme, wird der RTF-Text, der ja die Formatierungen enthält, abgeschnitten, obwohl das Feld groß genug ist. Ich steh irgendwo auf dem Schlauch... Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Ich weiß nur, dass beim Zugriff auf PostGres über ADO die Größe von Textmemos begrenzt ist.
Das Größenproblem liegt nicht auf der Datenbankseite und nicht in Delphi, sondern irgendwo dazwischen. Beim Zugriff über ODBC kann man in der Konfiguration unter "Options -> DataSource" einen Wert für "Max Varchar" eingeben (der unter ADO aber keine Auswirkung zu haben scheint). Kann man das beim Zugriff über die Zeos-Komponenten irgendwo konfigurieren? |
AW: Formatierten Text in PostgreSQL 9 speichern
Wenn ich die oben bereits verlinkte
![]() The bytea type supports two external formats for input and output: PostgreSQL's historical "escape" format, and "hex" format. Both of these are always accepted on input. The output format depends on the configuration parameter bytea_output; the default is hex. (Note that the hex format was introduced in PostgreSQL 9.0; earlier versions and some tools don't understand it.) The SQL standard defines a different binary string type, called BLOB or BINARY LARGE OBJECT. The input format is different from bytea, but the provided functions and operators are mostly the same. Ich würde da jetzt mal herumexperimentieren (oder besser: nein, ich würde jetzt nicht, aber du könntest). Schau dir auch mal die beiden Tabellen in der verlinkten Doku an, da gibt es auch sog. Ausgabe-Parameter, die darüber entscheiden, was wie ausgegeben wird, insbesondere, wenn Zeichen zuvor maskiert wurden. Gerade finde ich noch einen Hinweis in meinem PostGre-Handbuch: Um den Datentyp bytea zu verwenden, sollten Sie einfach die Methoden getBytes(), setBytes(), getBinaryStream() oder setBinaryStream() anwenden. |
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo,
der RTF-String ist schon abgeschnitten, wenn ich in innerhalb des Programms in einen Stream und wieder zurück wandele, ohne dass die Datenbank im Spiel ist. Perlsau hat schon recht, ich muss da experimentieren und die richtige Kombination aus Stream-Konfiguration, Komponenteneinstellung und Wissen aus Forenbeiträgen austüfteln. Jedenfalls danke für die Ideen, ich werde berichten. Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Liste der Anhänge anzeigen (Anzahl: 1)
Sorry, aber das kann ich nun überhaupt nicht nachvollziehen. Im Anhang eine Zip-Datei mit einem Test-Projekt (D2009), das einwandfrei funktioniert: Die geladene RTF-Datei wird via TMemoryStream in ein zweites RichEdit kopiert, und zwar vollständig fehlerfrei:
Delphi-Quellcode:
unit UnitMain;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls; type TFormMain = class(TForm) Panel_Main: TPanel; Panel_Navi: TPanel; Rich_Quelle: TRichEdit; Rich_Ziel: TRichEdit; Btn_Close: TButton; OpenDlg: TOpenDialog; SaveDlg: TSaveDialog; Btn_Open: TButton; Btn_Save: TButton; Btn_Kopie: TButton; procedure Btn_CloseClick(Sender: TObject); procedure Btn_OpenClick(Sender: TObject); procedure Btn_SaveClick(Sender: TObject); procedure Btn_KopieClick(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var FormMain: TFormMain; implementation {$R *.dfm} procedure TFormMain.Btn_CloseClick(Sender: TObject); begin Close; end; procedure TFormMain.Btn_OpenClick(Sender: TObject); begin If Not OpenDlg.Execute Then Exit; Rich_Quelle.Lines.LoadFromFile(OpenDlg.FileName); end; procedure TFormMain.Btn_SaveClick(Sender: TObject); begin If Not SaveDlg.Execute Then Exit; Rich_Ziel.Lines.SaveToFile(SaveDlg.FileName); end; procedure TFormMain.Btn_KopieClick(Sender: TObject); Var S : TMemoryStream; begin S := TMemorystream.Create; Try Rich_Quelle.Lines.SaveToStream(S); S.Position := 0; Rich_Ziel.Lines.LoadFromStream(S); Finally S.Free; End; end; end. |
AW: Formatierten Text in PostgreSQL 9 speichern
Mal ne Frage:
Wie groß ist den der Text im RichEdit? Per Default kann das RichEdit nur 64K aufnehmen. Vielleicht wird zwar mehr Text angezeigt, aber beim Speichern nur die 64K exportiert. Zu Bedenken ist hier der Unterschied zwischen Text und RTF. |
AW: Formatierten Text in PostgreSQL 9 speichern
Es ist schon sehr abenteuerlich, was du da mit dem Stream veranstaltest (casten des Stream-Inhalts mit
Delphi-Quellcode:
).
PChar
Wenn du den RTF-String haben möchtest, dann nimm doch einfach
Delphi-Quellcode:
Wenn du in ein Blob-Feld speichern möchtest, dann nimm doch die einfache Variante:
function TfrmMain.GetRTFText: string;
begin Result := redt1.Lines.Text; end;
Delphi-Quellcode:
und das Lesen geht ähnlich kompliziert
// DataSet und Name des Felds musst du anpassen
MyDataSet.FieldByName( 'MyRtfBlobField' ).Assign( redt1.Lines );
Delphi-Quellcode:
// DataSet und Name des Felds musst du anpassen
redt1.Lines.Assign( MyDataSet.FieldByName( 'MyRtfBlobField' ) ); |
AW: Formatierten Text in PostgreSQL 9 speichern
Hmm..
ich glaube es könnte am fehlenden
Delphi-Quellcode:
liegen
ARichEdit.PlainText := False;
![]()
Delphi-Quellcode:
function GetRTFText(ARichEdit: TRichedit): string;
var ss: TStringStream; emptystr: string; begin emptystr := ''; ss := TStringStream.Create(emptystr); try ARichEdit.PlainText := False; ARichEdit.Lines.SaveToStream(ss); Result := ss.DataString; finally ss.Free end; end; @Sir Rufo Meines Wissens liefert Result := redt1.Lines.Text; nur den reinen Text, ohne RTF-Formatierungen. |
AW: Formatierten Text in PostgreSQL 9 speichern
wenn ich mal aus der OH zitieren darf:
Zitat:
K-H |
AW: Formatierten Text in PostgreSQL 9 speichern
Liste der Anhänge anzeigen (Anzahl: 1)
Bevor jetzt noch mehr Verwirrung entsteht: Das oben angehängte Projekt arbeitet mit TRichEdit, also den mitgelieferten VCL-Komponenten. Diese arbeiten bei größeren RTF-Dateien nicht mehr fehlerfrei, was an der erwähnten 64-KB-Grenze liegen mag. Verwendet man stattdessen die RichEdit-Komponenten der Jedi-Sammlung, die da heißt TJvRichEdit, lassen sich auch größere RTF-Dateien fehlerfrei einlesen, abspeichern und zwischen zwei Komponenten via Stream kopieren. Natürlich sollte das Property PlainText stets auf false stehen, wenn man Textformatierungen benötigt, sonst hätte man nur den reinen Text, wie er im Property Text der Lines-Eigenschaft vorliegt.
Zum Testen hab ich nochmal eine kompilierte Exe mit JediRichEdits angefügt. |
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo zusammen,
danke für Eure Antworten und Testprojekte. Das Testprojekt von Perlsau funktioniert einwandfrei. Wenn aus dem gleichen Stream wieder ausgelesen wird, klappt das auch bei mir. Sobald ich aber den Inhalt des Streams zwischenspeichere (deswegen der Cast nach PChar), wird er abgeschnitten. Ich weiss jetzt allerdings auch nicht, wie ich aus dem Stream etwas erhalte, was ich in einer Datenbank speichere, ggf. mit Assign? @HolgerX: Der Text, den ich zum Test verwende, ist nur ca. 100 Zeichen lang, damit sollte es keine Probleme geben, Plaintext steht auch immer auf false. Ich forsche weiter. Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Hmm..
Kann es sein, das in deinem Rückgabe-String (RTF-String) an der Stelle, an der abgeschnitten wird ein #0 vorkommt? Ein PChar endet beim ersten Vorkommen eines #0-Zeichens ;) Bei einem String kann es aber weiter gehen .. Verwende doch statt des MemoryStreams einen StringSteam, wie aus dem Source von meinem Post #13, dann fällt die Verwendung des PChar wegs. Außerdem liefert glaube ich ein SaveToStream eines RichEdits einen AnsiString und das würde weitere Probleme mit Pchar geben, da dies als UniCode eine WideChar und kein AnsiChar ist.. ;) |
AW: Formatierten Text in PostgreSQL 9 speichern
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe jetzt innerhalb des Programms eine Testmethode zum Experimentieren erstellt, dabei wird der Inhalt eines JvRichEdits in einen Stream und von da aus in eine String-Variable geschrieben. Anschließend wird mit der String-Variable ein Stream gefüllt und dieser wiederum in ein zweites JVRichedit geladen. Dabei wird aus Zitat:
Hier die Testmethode:
Delphi-Quellcode:
Sehr seltsam das ganze...irgendwo ist der Wurm drin..
procedure TfrmMain.btn5Click(Sender: TObject);
var FStream: TStringStream; strtest: widestring; teststring: string; begin // Zuerst in Stream umwandeln: try FStream := TStringStream.Create(teststring); FStream.Clear; edt1.Lines.SaveToStream(FStream); FStream.Position := 0; strtest := FStream.DataString; finally FStream.Free; end; // und wieder zurück: edt2.lines.clear; try FStream := TStringStream.Create(teststring); FStream.Clear; FStream.WriteBuffer(strtest[1], Length(strtest)); FStream.Position := 0; edt2.Lines.LoadFromStream(FStream); finally FStream.Free; end; end; Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Du mußt den Inhalt des Streams doch nicht in einem PChar zwischenspeichern. Ich kann mir dafür keinen zwingenden Grund vorstellen. Belasse doch den Inhalt im Stream, nenne in meinetwegen MeinGlobalerMemoryStream und deklariere ihn global bzw. wenn du ihn nur in dieser Unit benötigst, im Private-Abschnitt. Den Inhalt des Streams kannst du dann auch wunderbar in ein Blobfeld schreiben bzw. umgekehrt ein Blobfeld in einen Stream gießen. Natürlich kommt es zu Verlusten, wenn du Inhalte in Typen speicherst, die dafür nicht geeignet sind. Die Leerzeichen zwischen jedem einzelnen Zeichen sind ein Signal dafür, daß du ehemaligen Unicode-Text mit einer nicht unicodefähigen Komponente darstellst oder sicherst. Das heißt, jedes zweite Zeichen ist nicht darstellbar, weil Unicode hier zwei Byte pro Zeichen belegt und das zweite Byte ein nicht darstellbares Zeichen ist, jedoch zum ersten Byte gehört und in Unicode-Darstellung auch korrekt dargestellt würde. Laß also einfach diesen Unsinn mit dem Typecast nach PChar weg, behalte das Zeug im Stream und gut ist.
|
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo Perlsau,
in der Methode oben ist doch gar kein Typecast mehr drin... :), aber das mit dem Unicode leuchtet mir ein. Üblicherweise baue ich meine SQLs als String zusammen (ich verwende keine Datasets), so dass ich halt vor dem Problem stehe, den Inhalt des Streams in ein SQL einfügen, da fehlt mir wohl das Wissen. Also (verkürzt) so:
Code:
Gruß
SQL := 'insert into notes (notizfeld) values (<hier sollte der Stream dann hin...>)';
ExecSQL; Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Wie Perlsau bereits schrieb, ist nun das Problem dein UniCode!
RichEdit -> AnsiStr... Mach aus deinem
Delphi-Quellcode:
doch mal
var
FStream: TStringStream; strtest: widestring;
Delphi-Quellcode:
und setze bei FStream := TStringStream.Create('',e); für e das Encoding für ANSI..
var
FStream: TStringStream; strtest: AnsiString; |
AW: Formatierten Text in PostgreSQL 9 speichern
@Perlsau :thumb:
Um das ganze ein wenig zu erhellen:
Delphi-Quellcode:
Sodele, und jetzt achauen wir uns einmal das Encoding an. Was fällt uns auf?
procedure StreamCopyStrings( Source, Destination: TStrings );
var lTempStream: TMemoryStream; begin lTempStream := TMemoryStream.Create; try Source.SaveToStream( lTempStream ); lTempStream.Position := 0; Destination.LoadFromStream( lTempStream ); finally lTempStream.Free; end; end; procedure TForm1.Button1Click( Sender: TObject ); begin StreamCopyStrings( RichEdit1.Lines, Memo1.Lines ); Label1.Caption := Memo1.Lines.Encoding.EncodingName; end; Und wenn wir das beim Einlesen in den StringStream nicht berücksichtigen, dann bekommen wir eben nur Grütze (wie man sehen kann). Also entweder einfach in den (Binär)-Stream packen und wieder auslesen oder man weiß was man tut und kennt sich mit dem Encoding Geraffel aus :stupid: |
AW: Formatierten Text in PostgreSQL 9 speichern
Hallo,
ich bin schon mal einen Schritt weiter, mit der Umstellung auf AnsiString kommt der Testtext bei der obigen Methode unverändert im zweiten Richedit an.:thumb: Jetzt muss ich das Ganze nur noch in die Datenbank bringen. Gruß Frank |
AW: Formatierten Text in PostgreSQL 9 speichern
Das Einfügen in die Datenbank sollte dann eigentlich über Parameter funktionieren:
Delphi-Quellcode:
Per Stream müsste das auch gehen, ohne diesen Stringumweg:
ZQuery1.SQL.Text := 'insert into notes (notizfeld) values (%Value)';
ZQuery1.ParamByName('Value').AsString := QuotedStr(DeineStringGetFunktion); ZQuery1.ExecSQL;
Delphi-Quellcode:
var lTempStream: TMemoryStream; begin lTempStream := TMemoryStream.Create; try edt1.Lines.SaveToStream(lTempStream); lTempStream.Position := 0; ZQuery1.SQL.Text := 'insert into notes (notizfeld) values (%Value)'; ZQuery1.ParamByName('Value').LoadFromStream(lTempStream ,ftBlob); ZQuery1.ExecSQL; finally lTempStream.Free; end; end; (* Typ musst Du passend auswählen: TFieldType = (ftUnknown, ftString, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime, ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar, ftWideString, ftLargeint, ftADT, ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob, ftVariant, ftInterface, ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd); *) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:50 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 by Thomas Breitkreuz