Seite 1 von 1

Generischer Ansatz für ostream& operator<<(...) m

Verfasst: 26. November 2008 10:32
von nasahl
Hallo,

ich möchte einen generischen Ausgabeoperator auf ostream für all QT-Klassen implementieren, die intern ein "QDataStream & operator<< ( QDataStream & stream, ... )" haben.

Das würde ungefähr so aussehen:

Code: Alles auswählen

template<class QTCLASS>
ostream& operator<<(ostream& oss, const QTCLASS& obj)
{
    QDataStream str;
    str << obj;
    std::string s = convert2StringButIDontKnowHow( str );
    oss << s;
    return oss;
}
Hat jemand eine Idee wie das gehen könnte? Ich kenn mich mit QT nicht so gut aus.


Danke schon mal, Christof

Verfasst: 26. November 2008 17:46
von scn
Hallo Christof,

QDataStream serialisiert binäre Daten auf ein Device. Anstelle einer Datei verwendest du ein QByteArray. Die Daten kannst du dann mit constData() als const char * auslesen.

Also, um dein Beispiel aufzugreifen, könnte es dann so aussehen:

Code: Alles auswählen

template<class QTCLASS>
ostream& operator<<(ostream& oss, const QTCLASS& obj)
{
    QByteArray data;
    QDataStream str(&data, QIODevice::ReadWrite);
    str << obj;
    oss << data.constData();
    return oss;
}
Gruß Thomas

Verfasst: 27. November 2008 07:48
von nasahl
Vielen Dank für die konkrete Antwort.

Was ich aber nicht verstehe, ist, dass der folgende Code:

Code: Alles auswählen

template<class QTCLASS>
std::string convert2String( const QTCLASS& obj )
{
    QByteArray data;
    QDataStream str(&data, QIODevice::ReadWrite);
    str << obj;
    return std::string( data.constData() );
} 
...
    QRect r(1, 2, 3, 4);
    std::cout << "r: " << convert2String(r) << std::endl;

eine leere Ausgabe für r produziert.

Was ist daran falsch ?

Christof

Verfasst: 27. November 2008 08:13
von Christian81
nasahl hat geschrieben: Was ist daran falsch ?
scn hat geschrieben: QDataStream serialisiert binäre Daten auf ein Device
Genau das.
Wie kommst Du darauf das die Binärdaten als string irgend etwas vernünftiges anzeigen?

Verfasst: 27. November 2008 16:12
von nasahl
Mein Beitrag 2 ist nur eine Umsetzung der Idee von Beitrag 1. Vielleicht kann man das Problem so nicht lösen. Wie macht man es aber dann?

Christof

Verfasst: 27. November 2008 21:43
von scn
OK. Vielleicht war ich mit constData() auch zu schnell. Binäre Daten können natürlich auch NULL-Bytes enthalten. Werden diese Daten als const char * interpretiert und in einen std::string umgewandelt ist natürlich beim ersten '\0' die Zeichenkette zu Ende.
Deshalb wahrscheinlich die leere Ausgabe.
Bei der Wandlung des QByteArray in einen QString bleiben NULL-Bytes erhalten. Also versuch mal

Code: Alles auswählen

template<class QTCLASS>
std::string convert2String( const QTCLASS& obj )
{ 
    QByteArray data;
    QDataStream str(&data, QIODevice::ReadWrite);
    str << obj;
    return QString(data).toStdString();
}
Gruß Thomas

Verfasst: 28. November 2008 13:59
von RHBaum
Aehm, nur kurz ne Frage ...

warum ein QByteArray übern den umweg via (Q)string serialisieren ???
und warum der Umweg ueber QDataStream?
A data stream is a binary stream of encoded information which is 100% independent of the host computer's operating system, CPU or byte order. For example, a data stream that is written by a PC under Windows can be read by a Sun SPARC running Solaris.
Ist deine Order im QByteArry denn eigentlich genau spezifiziert ?
Ist auch genau spezifiziert, wie die Ausrichtung deiner Nutzdaten im "bytefeld" eigentlich ist ?
Normal ist das bei Motorola und Intel nicht gleich.
Ein Feld von Ints z.b. was nen mac geschrieben hat, musst "ziemlich aufwendig" nach intel konvertieren (sawtooth methode).

Wenn das ned beruecksichtigs, kriegst sowieso probleme beim serialisieren ....

wenn Motorola / intel keine bedeutung fuer dich hat, brauchst den Umweg ueber QDataStream ned ....

wenn es doch fest definiert ist, ist dein bytearray selber schon plattformunabhaengig, und Du brauchst QDataStream ned dazu ...

Das ist wohl auch der grund, warum es keinen fertigen operator fuer QDatastream und QByteArry scho gibt.

Also pump deine daten lieber per write() direkt ins QIODevice rein.

Felder von ints, oder andere dinge soltest du nicht ueber QByteArray direkt serialisieren, wenn Prozesseurunabhaengigkeit eine rolle spielt, sondern du solltest die Daten nach ihren folgen vorher aufloesen, also wenn 25 ints speichern willst, dann 25 in den datastream, und dann alle 25 werte hinterher. nur das garantiert dir die unabhaengigkeit.
Speicherbereiche aus unterschiedlichen daten (Structs, Arrays) sind nicht prozessorunabhaengig !!!

Ciao ....

Verfasst: 28. November 2008 14:16
von AuE
Bei Lade- und Speichervorgängen in Registern und Speichern gibt es zwei Anordnungssysteme in dem die Bytes eingelesen werden: Das Little-Endian-Format und das Big-Endian-Format.



Big- und Little-Endian-Formate



Im Gegensatz zu Big Endian ist Little Endian ein Format für die Übertragung oder Speicherung binärer Daten, in denen das Least Significant Byte (LSB) an erster Stelle kommt und auf der niedrigsten Speicheradresse gespeichert wird. So wird das Byte E3 von der hexadezimalen Zahl 6FE3 im Little-Endian-Format auf dem Speicherplatz mit der niedrigsten Adresse gespeichert.

Nach diesem Prinzip arbeiten u. a. Intel, die VAX von DEC, DEC-Alpha und MIPS-Chips.