Longblob(JPG) aus MySQL in TImage ausgeben
-
Hi,
Mein Problem bezieht sich auf Borland C++ Builder 6 und MySQL 5.0.16.
Ich habe eine Datenbank unter MySQL laufen, in der sich Bilder befinden, die ich ausgeben will. Das Feld "image", in der sich die Bilder befinden, besitzt das Format "longblob" und die Bilder sind im Format JPG.Eine Ausgabe über DBImage ist nicht möglich, da die Bilder als JPG gespeichert sind und nicht als BMP. Aus diesem Grunde habe ich versucht, die Bilder in einem TImage auszugeben.
Mit Hilfe eines anderen Forums, wurde dieser Quelltext fertig.
Jedoch hängt man an der unten beschriebenen Stelle fest. Aus diesem Grunde hoffe ich, dass ihr weiterhelfen könnt.TStream *pStream; TJPEGImage *pJPG; Form2->Query1->Fields->CheckFieldNames("image"); Form2->Query1->Fields->FieldByName("image"); pStream = Form2->Query1->CreateBlobStream(Form2->Query1->Fields->FieldByName("image"),bmRead); AnsiString T; -> Kontrolle ob Daten sich im Stream befinden T = pStream->Size; Label5->Caption = T; -> Ausgabe der Größe (passt 100%tig) [b]pJPG->LoadFromStream(pStream);[/b] -> Abbruch: EAccess Violation Image1->Picture->Assign(pJPG);Alle anderen Felder der DB lese ich über Data Control Units aus, die auch funktionieren.
MfG
Ps.: Für jeden Denkanstoss bin ich dankbar.

-
Sagt dir das Schlüsselwort new etwas?
-
Ja, new dient (laut dem Buch von "Richard Kaiser") zur Speicherreservierung und dessen Ausgabe wärend der Laufzeit.
Jedoch weiß ich nicht genau, worauf du hinaus willst.Kann es sein das du dies meinst???
pStream = new TStream(Form2->Query1->CreateBlobStream(Form2->Query1->Fields->FieldByName("image"),bmRead));Glaube nicht, oder???
Dort bekomme ich die Fehlermeldungen:
E2352 Cannot create instance of abstract class 'TStream'
E2353 Class 'TStream' is abstract because of '_fastcall TStream::Read(void *,int) = 0'Soweit ich das deuten kann, verlangt der TSream einen Wert. Wenn ja, wo soll ich diesen eintragen.

Aber Warum? TSream bekommt doch einen Wert übergeben, diesen habe ich doch schon ausgegeben (zumindest seine Größe im "Label5").
Du musst "etwas" Nachsicht mit mir haben, innerhalb der Ausbildung habe ich nur programmiert und diese liegt leider schon ein paar Jahre zurück.
MfG
---------------------------------------------------------------------
Danke für den Hinweis, war genau der Richtige.

TStream *pStream; TJPEGImage *pJPG = new TJPEGImage();; pStream = Form2->Query1->CreateBlobStream(Form2->Query1->FieldByName("image"),bmRead); pJPG->LoadFromStream(pStream); Image1->Picture->Assign(pJPG); delete pStream; delete pJPG;
-
Hallo
nein die Fehlermeldugn heißt das TStream eine abstrakte Basiskalsse ist ohne vollständige Implementierung. Du must stattdessen eine Instanz von Klassen erstellen, die von TStream abgeleitet sind. Zum Beispiel TFileStream oder (das wäre wohl das richtige für dich) TMemoryStream. Und dann haben deren Konstruktoren auch keine Parameter. Das kannst du aber alles in der BCB-Hilfe nachlesen. Für die Grundlagen in objektorientierter Programmierung solltest du unbedingt ein entsprechendes Tutorial durcharbeiten.
bis bald
akari
-
Danke für den Link, werde mich mal daran zu schaffen machen.
Der Code aus der unteren Zeile funktioniert, warum dann eine abstrakte Klasse???
MfG
-
@1753: Dein Code ist so jetzt korrekt.
Die Methode CreateBlobStream erzeugt einen konkreten "TBlobStream", so daß du in deinem Aufruf einfach die abstrakte Klasse "TStream" benutzen kannst.
Nur wenn du genauere Infos über den BlobStream benötigst, müßtest du die Klasse "TBlobStream" benutzen.
-
Mit TBlobStream hat das ganze nicht funktioniert.
Ich bin zwar nicht sicher, aber es kam der "TBlobStream funktioniert nicht mit TStream" (so in etwa).Deswegen auch TStream.
Eine Frage, ist TBlobStream nicht von TStream abgeleitet???
MfG
-
Hallo,
Was funktioniert nicht? Versuch bitte die genaue Fehlermeldung zu posten. Sie läßt sich auch aus dem Anzeigefenster heraus kopieren.
TBlobStream ist von TStream abgeleitet, was dir ein Blick in die Hilfe zu TBlobStream (Hirarchie) auch verraten hätte.
-
Das TBlobStream von TStream abgeleitet wird, habe ich doch schon mitbekommen.
Zitat: "Eine Frage, ist TBlobStream nicht von TStream abgeleitet???"
Ich war mir aber nicht ganz sicher und deshalb habe ich nachgefragt.
Ich hätte das nicht auch weglassen können. OK?Der Code aus meinem zweiten Post hat auch funktioniert, doch als ich versucht habe
TBlobStream *pStream;zu schreiben/nutzen, da habe ich die Fehlermeldung bekommen, dass TBlobStream nicht in Verbindung mit TSream funktionieren würde.

MfG
-
Dann habe ich das mit dem nicht falsch verstanden.
Bei welcher Zeile kommt denn diese Fehlermeldung? Bei der Dekalrattion kann es ja nicht sein. Es fehlt also immernoch der relevante Code.
-
Wenn ich versuche TBlobStream anstatt TSream zu nutzen, bekomme ich die Fehlermeldungen, die hinter dem Code stehen.
TBlobStream *pBlob = new TBlobStream(); [b]//Could not find a match for 'TBlobStream::TBlobStream()'[/b] TJPEGImage *pJPG = new TJPEGImage(); pBlob = Form1->Query1->CreateBlobStream(Form1->Query1->FieldByName("image"),bmRead); [b]//Cannot convert 'TStream *' to 'TBlobStream *'[/b] pJPG->LoadFromStream(pStream); Image1->Picture->Assign(pJPG); delete pBlob; delete pJPG;Wenn ich versuche bei TBlobStream das new wegzulassen (Siehe Code),
TBlobStream *pBlob; TJPEGImage *pJPG = new TJPEGImage(); pBlob = Form1->Query1->CreateBlobStream(Form1->Query1->FieldByName("image"),bmRead); pJPG->LoadFromStream(pStream); Image1->Picture->Assign(pJPG); delete pBlob; delete pJPG;bekomme ich den Fehler: **Cannot convert 'TStream ' to 'TBlobStream '
ABER, mit TStream funktioniert das ganze und dann sieht der Code auch so aus:
void __fastcall TForm3::Button2Click(TObject *Sender) { TStream *pStream; TJPEGImage *pJPG = new TJPEGImage(); pStream = Form1->Query1->CreateBlobStream(Form1->Query1->FieldByName("image"),bmRead); pJPG->LoadFromStream(pStream); Image1->Picture->Assign(pJPG); delete pStream; delete pJPG; }MfG
-
Na dann mach es auch so wie es funktioniert. Das mit dem new ist sowieso Unsinn. Da würdest du Speicher für ein TBlobStream-Objekt bereitstellen. Dann überschreibst du deinen Zeiger bei Aufruf von CreateBlobStream gleich wieder -> Speicherleck. Außerdem verlangt der Konstruktor von TBlobStream 2 Parameter (1. Fehlermeldung).
Bei der zweiten Variante müsstest du einfach nach TBlobStream casten (dynamic_cast), da CreateBlobStream ja ein TStream-Objekt zurückliefert. Probier das hier malTBlobStream *pBlob; TJPEGImage *pJPG = new TJPEGImage(); pBlob = dynamic_cast<TBlobStream*>(Form1->Query1->CreateBlobStream(Form1->Query1->FieldByName("image"),bmRead)); if( pBlob ) // Kontrolle ob es wirklich ein TBlobStream ist { pJPG->LoadFromStream(pStream); Image1->Picture->Assign(pJPG); delete pBlob; } delete pJPG;
-
@Braunstein
Danke, funktioniert auch wunderbar.Das mit "dynamic_cast" habe ich noch nicht gekannt, aber das Tutorial von "akari" hat das gut erklärt.
@ALL
Danke für Eure Hilfe, echt SUPER hier!!!
-
Wenn jemand noch Lust und Laune hat, ich hätte da noch ein "kleines" Problem.
Es bezieht sich auch auf ein Image und meine Datenbank.Ich versuche aus einem Image heraus, ein Bild (JPG) in der Datenbank zu speichern.
Ohne Erfolg!!!Als erstes habe ich über TOpenPictureDialog ein Bild geladen. Funktioniert!!!
void __fastcall TForm4::Button2Click(TObject *Sender) { if (OpenPictureDialog1->Execute()) { Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName); } }Danach habe ich versucht, das Image auszulesen und in einen TJPEGImage zu speichern. Funktioniert auch!!!
Doch aus dem TJPEGImage die Daten in ein TBlobStream zu bekommen schlägt fehl.Mein Versuch:
TBlobStream *pBlob; TJPEGImage *pJPG = new TJPEGImage(); pBlob = dynamic_cast<TBlobStream*>(Form1->Query1->CreateBlobStream(Form1->Query1->FieldByName("image"),bmRead)); Image1->Picture->Graphic->SaveToStream(pBlob);Leider komme ich dann hier auch nicht weiter.

Ich kann den pBlob wieder in einem Image ausgeben, aber nicht an die Datenbank.INSERT mit den "Normalen" Datensätzen aus den Edit- feldern funktioniert.
(Textbasiert)Form1->Query1->Close(); Form1->Query1->SQL->Clear(); Form1->Query1->SQL->Add("INSERT INTO film (titel, jahr, fsk, laufzeit, genre_id, beschreibung, [b]image[/b]) VALUES ('"+Edit1->Text+"','"+Edit2->Text+"','"+ Edit3->Text+"','"+Edit4->Text+"','"+iRB+"','"+RichEdit1->Text+"','"+[b]pBlob[/b]+"')"); Form1->Query1->ExecSQL();Fehlermeldung hier: pBlob ist kein AnsiString. Der Rest funzt!
MfG
@Braunstein
Vielleicht hast du wieder einen spitzen Vorschlag.
-
Hallo
Doch aus dem TJPEGImage die Daten in ein TBlobStream zu bekommen schlägt fehl.
Das heißt? Fehlerbeschreibung?
Fehlermeldung hier: pBlob ist kein AnsiString. Der Rest funzt!
Die Fehlermeldung ist doch aussagekräftig : SQL-Anweisungen sind immer Text. Du kannst nicht einfach einen Byte-Strteam hinzuaddieren. Sondern der muß Byte für Byte in Textformat konvertiert werden, wo die nicht darstellbaren Zeichen durch Hex- oder Oktalwerte maskiert werden. Als Beispiel hier die Umsetzungstabelle für PostgreSQL. Ob das so standardisiert ist weiß ich nicht, vermute aber schon.
bis bald
akari
-
-
Den Blob-Stream sollte man doch besser über einen Parameter einfügen.
Evtl. soForm1->Query1->SQL->Add("INSERT INTO film (titel, jahr, fsk, laufzeit, genre_id, beschreibung, image) VALUES ('"+Edit1->Text+"','"+Edit2->Text+"','"+ Edit3->Text+"','"+Edit4->Text+"','"+iRB+"','"+RichEdit1->Text+"',:imageblob)"); Form1->Query1->Params->ByName("imageblob")->LoadFromStream(pBlob); Form1->Query1->ExecSQL();Ist jetzt nicht getestet.
-
Danke für Deine Hilfe.
Ich hab das Ganze mal eingegeben, jedoch ByName ist kein Bestandteil von Parms. (laut CBuilder)Form1->Query1->Params->ByName("imageblob")->LoadFromStream(pBlob);Dann hab ich mal nachgesehen was es denn unter Parms mit "ByName" so gibt.
Form1->Query1->SQL->Add("INSERT INTO film (titel, jahr, fsk, laufzeit, genre_id, beschreibung, image) VALUES ('"+Edit1->Text+"','"+Edit2->Text+"','"+ Edit3->Text+"','"+Edit4->Text+"','"+iRB+"','"+RichEdit1->Text+"',:imageblob)"); Form1->Query1->Params->[b]ParamByName[/b]("imageblob")->LoadFromStream(pBlob); Form1->Query1->ExecSQL();Soweit ganz gut, jedoch kommt dann die Meldung LoadFromStream hat zu wenig Argumente.
Ok, dann hab ich mir gedacht, da es sich um den Feldtyp LongBlob in der Datenbank handelt, übergebe ich diesen auch mit ftBlob
Form1->Query1->SQL->Add("INSERT INTO film (titel, jahr, fsk, laufzeit, genre_id, beschreibung, image) VALUES ('"+Edit1->Text+"','"+Edit2->Text+"','"+ Edit3->Text+"','"+Edit4->Text+"','"+iRB+"','"+RichEdit1->Text+"',:imageblob)"); Form1->Query1->Params->ParamByName("imageblob")->LoadFromStream(pBlob,[b]ftBlob[/b]); Form1->Query1->ExecSQL();Falsch gedacht, jetzt bekomme ich die Fehlermeldung EAccessViolation in Adresse 4002EAEF im Modul "rtl60.bpl". Lesen von Adresse 5D010AAB gestoppt.

Ich hab mir das von MySQL durchgelesen, die sagen ja zum Schluß man solle lieber einen Blob-Typen verwenden, welchen ich ja benutze.
Meinst Du ich solle die Datenbank überarbeiten, oder nur die SQL-Anweisung???
-
Hallo
Ich hab mir das von MySQL durchgelesen, die sagen ja zum Schluß man solle lieber einen Blob-Typen verwenden, welchen ich ja benutze.
Meinst Du ich solle die Datenbank überarbeiten, oder nur die SQL-Anweisung???
Nein du must hier zwischen dem MySQL-Spaltentyp Blob und der Builder-Klasse TBlobStream unterscheiden. Die Aussage aus der MySQL-Doku bezieht sich auf ersteres, was bei dir aber schon erledigt ist (wenn du den Spaltentyp Blob schon verwendest)
Sondern bei dir geht es um die korrekte Integration des BlobStreams in eine bereits korrekte SQL-Anweisung. Offenbar brauchst du die Umwandlung nicht selber machen. Worum du den Fehler bekommst kann ich aber nicht nachvollziehen.
bis bald
akari
-
Anscheinend muß der BlobStream doch gewandelt werden, denn wenn ich versuche pBlob
in der SQL-Anweisung zu integrieren, bekomme ich die Meldung:
*'operator+' not implemented in type 'AnsiString' for arguments of type 'TBlobStream 'SQL Anweisung:
Form1->Query1->SQL->Add("INSERT INTO film (titel, jahr, fsk, laufzeit, genre_id, beschreibung, image) VALUES ('"+Edit1->Text+"','"+Edit2->Text+"','"+ Edit3->Text+"','"+Edit4->Text+"','"+iRB+"','"+RichEdit1->Text+"','"[b]+pBlob+[/b]"')");Die gleiche Fehlermeldung kommt auch, wenn ich versuche pJPG anstatt pBlob zu verwenden. Auch Image1 direkt anzugeben schlägt fehl, gleiche Meldung.
Herkunft pJPG
TJPEGImage *pJPG = new TJPEGImage(); pJPG->Assign(Image1->Picture); // Übergabe des Images an pJPGIst es denn nicht möglich, das Image in Binärdaten zu wandeln.
Denn alle Informationen innerhalb des LongBlob-Feldes werden ja auch Binär gespeichert.MfG