Hallo,
ich habe ein Problem mit einer Datenbankanwendung. Das Problem besteht darin, dass beim Schreiben von Binärdaten (in meinem Fall JPG-Bilder) die Daten falsch übetragen werden. Hier die Details:
Bei der Datenbank handelt es sich um eine MySQL-Datenbank, die mit UTF-8 Kodierung aufgesetzt ist, da Texte in verschiendenen Sprachen gespeichert werden müssen. Mit dem Speichern von Textfeldern klappt auch alles wunderbar. Nun möchte ich aber auch Bilder in einer BLOB-Spalte der MySQL Datenbank speichern. Hierzu verwende ich den folgenden Code:
QSqlRecord rec = m_driver->record("tbdocdata");
rec.setValue("docid", docId);
rec.setValue("docdata", data);
QSqlQuery iquery(m_driver->sqlStatement(QSqlDriver::InsertStatement, "tbdocdata", rec, false));
Bei 'data' handelt es sich um einen QVariant, welches mit einem QByteArray mit den Bilddaten gefüllt ist. Der Member m_driver enthält den von der QSqlDatabase gelieferten Treiber.
In der Tabelle steht anschliessend allerdings Müll. Ich habe den Weg der Daten mit einem Debugger verfolgt und weiss jetzt, dass es bei der Hin- und Herwandlung der Daten zwischen QByteArray und QString zu Problemen kommt. Es passiert nämlich folgendes:
Beim Zusammenbau des Insert-Statements durch den Treiber wird das QByteArray zunächst mittels der Funktion
mysql_real_escape_string aufbereitet. Danach werden die Daten in einen QString gewandelt. Dies geschieht mit dem vom Treiber bei der Datenbank ermittelten UTF8-Codec (tc->toUnicode(buffer)). Dabei wird davon ausgegangen, dass es sich um UTF-8 kodierte Daten handelt. Dies ist aber nicht der Fall!
Also dachte ich, ich kann das Problem umgehen indem ich den INSERT-String selber zusammenbaue (allerdings muss ich dann selber auf die Funktion mysql_real_escape_string zugreifen, was meinen Code natürlich von MySQL abhängig macht). Doch auch das geht schief, weil nämlich beim Absetzen des Statements die umgekehrte Wandlung von QString in QByteArray stattfindet. Hier der entscheidende Code im MySQL-Treiber:
const QByteArray encQuery(fromUnicode(d->driver->d->tc, query));
Beim Codec handet es sich wie gesagt um den UTF8-Codec. Dieser soll hier aber gar nicht verwendet werden. Ich habe keine Ahnung, wie ich dieses Problem umschiffen soll. Der letzte Ausweg wäre dann höchstens die MySQL-C-API direkt aufzurufen. Doch das hebt dann die Datenbankunabhängigkeit endgültig auf.
Kann mir jemand einen Tipp geben, wie ich weiter vorgehen kann?
Vielen Dank im Voraus,
Rainer
PS: Das Laden von in der Datenbank abgelegten Bildern klappt übrigens einwandfrei. Hier findet aber auch keine Wandlung nach QString statt.
Binärdaten in MySql Datenbank mit Utf8-Kodierung schreiben
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Re: Binärdaten in MySql Datenbank mit Utf8-Kodierung schreib
Dein Feld in der DB ist doch hoffentlich ein Blob.
Ob QSqlRecord Blobs handeln kann weiß ich nicht - aber für Blobs muss man normalerweise Prepeared Queries verwenden was QSqlRecord wohl nicht tut.
Versuchs mal mit QSqlQuery::prepare()
Ob QSqlRecord Blobs handeln kann weiß ich nicht - aber für Blobs muss man normalerweise Prepeared Queries verwenden was QSqlRecord wohl nicht tut.
Versuchs mal mit QSqlQuery::prepare()
MfG Christian
'Funktioniert nicht' ist keine Fehlerbeschreibung
'Funktioniert nicht' ist keine Fehlerbeschreibung
Re: Binärdaten in MySql Datenbank mit Utf8-Kodierung schreib
Hallo Christian,
natürlich verwende ich einen Blob in der Datenbank. Das Auslesen der Daten funktioniert ja auch ohne Probleme.
Dein Tipp mit prepared-Query zu arbeiten war genau richtig. Ich habe es eben bereits erfolgreich ausprobiert. In diesem Fall werden die Daten tatsächlich ohne die Wandlung nach QString an die Datenbank übertragen. Zum Glück unterstützt MySQL ja inzwischen Prepared Queries.
Für alle Interessierten hier der abgewandelte Code:
QSqlQuery iquery;
iquery.prepare("insert into tbdocdata (docid,docdata) values (:id,:data)");
iquery.bindValue(":id", docid);
iquery.bindValue(":data", docdata);
if (!iquery.exec()) {
// Fehlermeldung
}
Nochmals vielen Dank,
Rainer
natürlich verwende ich einen Blob in der Datenbank. Das Auslesen der Daten funktioniert ja auch ohne Probleme.
Dein Tipp mit prepared-Query zu arbeiten war genau richtig. Ich habe es eben bereits erfolgreich ausprobiert. In diesem Fall werden die Daten tatsächlich ohne die Wandlung nach QString an die Datenbank übertragen. Zum Glück unterstützt MySQL ja inzwischen Prepared Queries.
Für alle Interessierten hier der abgewandelte Code:
QSqlQuery iquery;
iquery.prepare("insert into tbdocdata (docid,docdata) values (:id,:data)");
iquery.bindValue(":id", docid);
iquery.bindValue(":data", docdata);
if (!iquery.exec()) {
// Fehlermeldung
}
Nochmals vielen Dank,
Rainer