Binärdaten aus ADOQuery in MemoryStream schreiben



  • Hallo,

    trotz Suche im Internet und hier im Forum habe ich leider nichts passendes gefunden. Ich habe ein Feld in einer Datenbank, welches vom Datentyp OLE ist und in dem Binärdaten (in diesem Fall von Bildern) gespeichert sind. Per SQL-Abfrage lese ich diese nun aus, weiß allerdings nicht, wie ich die Daten aus der Abfrage in einen MemoryStream schreiben kann:

    ADOQuery1->SQL->Clear();
    ADOQuery1->SQL->Add("SELECT x FROM y WHERE id = 1;");
    ADOQuery1->Active = true;
    
    // Das TMemoryStream-Objekt heißt stream. Die entsprechenden Binärdaten kämen ja dann aus dieser Abfrage: ADOQuery1->Parameters->ParamByName("x");
    
    ADOQuery1->Active = false;
    ADOQuery1->SQL->Clear();
    
    stream->SaveToFile(sTEMPFILE);
    Image1->Picture->LoadFromFile(sTEMPFILE);
    

    Bin für Hilfe sehr dankbar.
    Gruß,
    Björn



  • Hallo? Hm, vielleicht sollte ich die Frage etwas allgemeiner Stellen:

    Wie schreibe ich binäre Daten in einen TMemoryStream?



  • Mit TMemoryStream::Write() !?



  • Ok, nach einigen Internetrecherchen und viel Bastelei habe ich es nun endlich geschafft.

    Allerdings hätte ich da noch eine wichtige Frage. Normalerweise muss ich den Speicher von erzeugten Objekten (instanzierten Klassen) ja wieder freigeben:

    TStringList *sl_LISTE = new TStringList();
    ...
    delete sl_LISTE;
    // evt. noch: sl_LISTE = NULL;
    

    In diesem Fall mit dem dynamic_cast funktioniert das jedoch nicht. Das Programm bricht immer mit einer Zugriffsverletzung ab, wenn ich versuche den Speicher wieder freizugeben:

    TBlobField *blob = dynamic_cast <TBlobField*> (ADOQuery1->FieldByName("picture"));
    ...
    delete blob;
    

    Ich weiß, ist wahrscheinlich wieder mal nur ein blöder Anfängerfehler. Irgendwo hab ich auch gelesen, dass man dynamic_cast nur in ganz seltenen Fällen verwenden soll. Aber anders konnte ich mein Problem ja nicht lösen. Der Query wird natürlich zuerst deaktiviert und geschlossen, bevor ich versuche den Speicher des blobs wieder freizugeben. Was mach ich falsch?

    Danke für die Hilfe.
    Björn



  • Bomania schrieb:

    Ok, nach einigen Internetrecherchen und viel Bastelei habe ich es nun endlich geschafft.

    Und wie? Es gehört zum guten Ton, auch selbst gefundene und/oder triviale Lösungen bekanntzugeben.

    Der Query wird natürlich zuerst deaktiviert und geschlossen, bevor ich versuche den Speicher des blobs wieder freizugeben. Was mach ich falsch?

    Mit *TBlobField blob = dynamic_cast ... hast du keinen Speicher reserviert sondern nur einen Zeiger auf eine bestehende Instanz eines TBlobField erstellt. Deshalb brauchst an der Stelle du keinen Speicher freizugeben, und darfst das auch nicht.

    Mit dem Thema des Threads hat das aber eigentlich nichts zu tun. Bitte möglichst die Faustregel beachten: ein Thema pro Thread, ein Thread pro Thema.



  • Jansen schrieb:

    Und wie? Es gehört zum guten Ton, auch selbst gefundene und/oder triviale Lösungen bekanntzugeben.

    Tut mir leid, war keine Absicht. Hier meine Lösung:

    #include "jpeg.hpp"
    ...
    void __fastcall Tfrm_MAIN::LoadPic(String ID)
    {
       TMemoryStream *stream = new TMemoryStream();
       TJPEGImage *JPEGImage = new TJPEGImage;
       try
       {
          // SQL-Statement setzen
          ADOQuery1->SQL->Clear();
          ADOQuery1->SQL->Add("SELECT picture FROM table WHERE id = '" + ID + "';");
          ADOQuery1->Active = true;
    
          // Binärdaten in Blobfeld laden und in Memorystream übertragen
          TBlobField *blob = dynamic_cast <TBlobField*> (ADOQuery1->FieldByName("picture"));
          blob->SaveToStream(stream);
          stream->Position = 0;
    
          // Nur versuchen zu laden, wenn auch Daten da sind -> sonst Zugriffsverletzung
          if(stream->Size != 0)
          {
             // Binärdatendaten in JPEG-Objekt übertragen und mit TImage verknüpfen
             JPEGImage->LoadFromStream(stream);
             Image1->Picture->Assign(JPEGImage);
             Image1->Visible = true;
          }
    
          // Query wieder säubern und schließen
          ADOQuery1->SQL->Clear();
          ADOQuery1->Active = false;
       }
       __finally
       {
          // Speicher des Stream-Objektes wieder freigeben
          delete stream;
          stream = NULL;
          // Speicher des JPEG-Objekts wieder freigeben
          delete JPEGImage;
       }
    }
    

    Jansen schrieb:

    Mit TBlobField *blob = dynamic_cast ... hast du keinen Speicher reserviert sondern nur einen Zeiger auf eine bestehende Instanz eines TBlobField erstellt.

    Ach ja stimmt. Das war doch die Sache mit new. Erst damit wird ein neues Objekt bzw. eine neue Instanz gebildet.

    Danke nochmals für die Hilfe.

    Gruß,
    Björn


Anmelden zum Antworten