[Qt-interest] Reading raw binary data

Murphy, Sean M. sean.murphy at gd-ais.com
Wed Jun 10 21:24:19 CEST 2009


> On Wednesday 10 June 2009 00:34:32 Anatoly Burakov wrote:
>> I am porting old custom-written DOS accounting app (Borland C++ 1.3
or
>> so) to QT4. This program reads and writes binary files. I need to
read
>> a float value from one of the binary files (probably other data types
>> too but i think if i figure out this one - others would be similar).
I
>> clearly see that there is a float value on the offset 0x0c (12) in
the
>> hex editor and i also have a BC++ source code which reads float value
>>
>> QT help suggests using QDataStream for this to work. So i try and use
it:
>> The problem is - QDataStream reads rubbish. I know what should be
>> there and i see that this is not what QDataStream reads. Any ideas
why
>> is this happening? Or am i missing something fundamental here? (maybe
>> it's the typecasting to blame? is there a way to read directly to
>> float value, without using QVariant?)
> 
> The reason is most probably that QDataStream aligns the data in its
own
> kind of way. But a QFile is a QIODevice and these also allow direct
> reading and writing of bytes.
> I noticed this when I was trying to read char* from a file with
> QDataStream, but had written these char* with QFile::write(). There
are
> aligned as short as possible in the file (hexdump shows it), but
> QDataStream expects them to be somewhere starting at byte three or
> more...

Make sure you read http://doc.qtsoftware.com/4.5/datastreamformat.html
and http://doc.qtsoftware.com/4.5/qdatastream.html#setByteOrder that
talks about how QDataStream reads and writes data to the device (file,
socket, etc.).  

Anatoly, if you want to read a float out with a QDataStream you should
just have to do:
  QDataStream ds(&someFile);
  float f;
  ds >> f;
But one thing that might be happening is that you aren't reading with
the correct byte order?  By default, a QDataStream is big endian.  If
the file you are reading was written by something else that wrote your
float out little endian, you could have that problem, if so add a:
  ds.setByteOrder(QDataStream::LittleEndian);
before you extract the float.

Arnold, in your case, extracting a char * from a QDataStream expects
there to be an unsigned int first that is the number of bytes to read,
then those many bytes.  So it pulls the first 4 bytes from the stream as
an unsigned int, then attempts to read that many bytes from the stream.
Since your write method didn't prepend your char* out with the unsigned
int, the QDataStream read attempt is corrupt.  Typically I've found it's
better to not mix & match reading/writing methods.  Either use
QDataStream for everything, or write the bytes out yourself.

Sean




More information about the Qt-interest-old mailing list