Reputation: 4004
I have some Delphi code that needs to be converted to Qt/C++.
The overall code reads a binary data file, and extracts portions of the data.
The Delphi code reads the file contents as follows:
var
m1 tmemorystream;
h1 integer;
.
.
m1 := tmemorystream.Create;
m1.LoadFromFile(paramstr[1]);
m1.Read (h1, 2);
Now, if the first 2 bytes in the file are "01 00", I would expect h1 to be 0x0100, but instead it seems to read it "Backwards" so the value in h1 is actually "00 01", i.e. 0x1.
The equivalent in Qt I have to read the file:
QFile fileIn(iFile);
if (!fileIn.open(QIODevice::ReadOnly)) return;
QByteArray m1 = fileIn.readAll();
How do I read the first 2 bytes into h1 the same as in the Delphi code? Delphi seems to have a way to specify a number of bytes to read from the stream/bytearray into an integer representation, but this seems to be reversed.
The equivalent I can think of in Qt to achieve the same result is:
QString tStg;
tStg.sprintf ( "0x%02x%02x", getUChar ( m1, 1), getUChar ( m1, 0) );
bool ok;
unsigned long h1;
h1 = tStg.toLong(&ok,16);
Seems long winded and inelegant ... granted I am a novice at C++.
So my question is first is there a direct equivalent of Delphi's tmemeorystream.Read in Qt?
Is there a better way to extract a range of bytes into a sinlge long/integer like in the Delphi code (variable h1)?
Upvotes: 1
Views: 604
Reputation: 2676
Duthomas is correct about endian problems. You must know your file's format to be able to read it correctly.
To answer the other part of your question, you need to use Qt's QIOStream class in order to access the file at a more granular level. You can also tell QUIStream which endian format a file has and it will fix numbers for you.
Upvotes: 2
Reputation: 10048
They are both wrong, actually. The problem is one of endianness. When you read an integer you should be aware of the file's endianness.
Open your file in a hex editor and take a look at the integer you are having trouble with. If the least-significant byte is first, it is little-endian. If the most-significant byte is first, it is big-endian. (And yes, this is all reference to Gulliver's Travels.)
When your C++ code reads the file, make sure to know how to fix it. The best way, in my opinion, is to always read by bytes and bit-shift the values into their proper places:
// little endian
int x = 0;
x = (unsigned char)f.get();
x |= (unsigned char)f.get() << 8;
x |= (unsigned char)f.get() << 16;
x |= (unsigned char)f.get() << 24;
// big endian
int x = 0;
x = (unsigned char)f.get();
x <<= 8; x |= (unsigned char)f.get();
x <<= 8; x |= (unsigned char)f.get();
x <<= 8; x |= (unsigned char)f.get();
You can, of course, speed things up by reading large chunks of the file into an array and decoding from the array instead of byte-by-byte file reads.
Hope this helps.
Upvotes: 2