PDA

View Full Version : vector of doubles to QByteArray



gmseed
14th October 2009, 16:21
Hi

I'm trying to convert a vector of doubles to a QByteArray; see code extract below.

It appears to pack the vector of doubles ok but the toOK booleans in toFloat(&toOK) are all set to false when trying to unpack.

Has anyone else ever done this operation before?

Thanks for your help as this is driving me crazy.

Graham



void testAddVertices(const QVector<VertexType>& vertices)
{
int numberVertices = vertices.size();

QByteArray byteArray;
QDataStream out(&byteArray,QIODevice::ReadWrite);

//double vx, vy, vz; // 64bit
float vx, vy, vz; // 32bit
for (int i=0; i<numberVertices; i++)
{
const VertexType& v = vertices[i];
vx = v.x(); vy = v.y(); vz = v.z();
out << vx; out << vy; out << vz;
}

byteArray = byteArray.toHex();
const char* data = byteArray.constData();
QString qdata(data);
std::string qdatas = qdata.toStdString();
std::cout << "qdata: " << qdatas << std::endl;

// extract
QByteArray byteArrayExtracted = QByteArray::fromHex(byteArray);
QBuffer buffer(&byteArrayExtracted);
//QBuffer buffer(&byteArray);
buffer.open(QIODevice::ReadOnly);
qint64 vertexComponentLength = 8;
qint64 vertexLength = 3*vertexComponentLength;
qint64 seekPos = 0;
qint64 numberBytesRead;
bool toOK, seekOK;
char* vxChar = new char[vertexComponentLength];
char* vyChar = new char[vertexComponentLength];
char* vzChar = new char[vertexComponentLength];
for (int i=0; i<numberVertices; i++)
{
numberBytesRead = buffer.read(vxChar,vertexComponentLength);

seekOK = buffer.seek(seekPos+vertexComponentLength);
numberBytesRead = buffer.read(vyChar,vertexComponentLength);

seekOK = buffer.seek(seekPos+2*vertexComponentLength);
numberBytesRead = buffer.read(vzChar,vertexComponentLength);

QByteArray vxCharArray(vxChar,vertexComponentLength);
//vxCharArray = QByteArray::fromHex(vxCharArray);
float vx = vxCharArray.toFloat(&toOK);
QByteArray vyCharArray(vyChar,vertexComponentLength);
//vyCharArray = QByteArray::fromHex(vyCharArray);
float vy = vyCharArray.toFloat(&toOK);
QByteArray vzCharArray(vzChar,vertexComponentLength);
//vzCharArray = QByteArray::fromHex(vzCharArray);
float vz = vzCharArray.toFloat(&toOK);

VertexType v(vx,vy,vz);
std::cout << "v(" << vx << ", " << vy << ", " << vz << ")" << std::endl;

// move to start of next vertex
seekPos += vertexLength;
}

// cleanup
delete vxChar; delete vyChar; delete vzChar;
}

yan
14th October 2009, 16:30
Hi.
Why you don't use QDataStream to unpack?

Your problème is maybe linked with the endian or float représentation use to write float to QByteArray

gmseed
15th October 2009, 10:40
Hi

QDataStream feeds through to the underlying QByteArray so I chose to operate on that directly.

Graham

yan
15th October 2009, 13:38
QDataSTream work in big endian by default.
http://doc.trolltech.com/4.6-snapshot/qdatastream.html#ByteOrder-enum


try qFromBigEndian to convert endian on the float readed.
http://doc.trolltech.com/4.6-snapshot/qtendian.html#qFromBigEndian-2

gmseed
16th October 2009, 15:03
Hi

The only way I could et it to work is to work through QDataStream for both << and >>; see pasted code below.

I need to index into the packed byte array and found:

QIODevice* device = in.device();

works on the underlying internal QBuffer.

As illustrated in the first post, if I operate on the QBuffer outside of the QDataStream I can't get it to work.

It's a strange one and can only think that if QDataStream is used throughout then the encoding is consistent.

Cheers

Graham




void testAddVertices(const QVector<VertexType>& vertices)
{
int numberVertices = vertices.size();

QByteArray byteArray;
QDataStream out(&byteArray,QIODevice::WriteOnly);

//double vx, vy, vz; // 64bit
float vx, vy, vz; // 32bit
for (int i=0; i<numberVertices; i++)
{
const VertexType& v = vertices[i];
vx = v.x(); vy = v.y(); vz = v.z();
out << vx; out << vy; out << vz;
}

std::cout << "byteArray length: " << byteArray.length() << std::endl;

// extract
QDataStream in(&byteArray,QIODevice::ReadOnly);
QIODevice* device = in.device();
qint64 vertexComponentLength = 4;
qint64 vertexLength = 3*vertexComponentLength;
qint64 seekPos = 0;
qint64 numberBytesRead;
bool toOK, seekOK;
float currentValue;
//float vx, vy, vz;
for (int i=0; i<numberVertices; i++)
{
// seek to start of new vertex
device->seek(seekPos);
in >> vx;

device->seek(seekPos+vertexComponentLength);
in >> vy;

device->seek(seekPos+2*vertexComponentLength);
in >> vz;

VertexType v(vx,vy,vz);
std::cout << "v(" << vx << ", " << vy << ", " << vz << ")" << std::endl;

// move to start of next vertex
seekPos += vertexLength;
}
}

yan
16th October 2009, 16:09
For me this work perfectly


#include <QtCore>

int main(int argc, char *argv[])
{

QByteArray byteArray;

//generate ten random float value
QVector<float> v;
for (int i =0; i < 10;++i)
{
v << 100. * qrand()/RAND_MAX;
}
//ouput vector
qDebug() << v;

//write float value to array
{
QDataStream out (&byteArray,QIODevice::WriteOnly);
foreach(float f,v)
{
out << f;
}
}

//read all float from array
QVector<float> v2;
{
QDataStream in(byteArray);
while (!in.atEnd())
{
float f;
in >> f;
v2 << f;
}
}
//ouput vector
qDebug() << v2;


return 0;
}