[Qt-interest] How to deal with pointers for a QDataStream?
Andre Somers
andre at familiesomers.nl
Wed Apr 21 10:24:03 CEST 2010
On 20-4-2010 22:24, Oliver Heins wrote:
>>> This is how I go: I write my MagicNumber and the highest unique id to
>>> the file. Then I traverse my QLinkedList<Token*>, writing the tokens:
>>>
>>> while (i.hasNext())
>>> out<< *(i.next());
>>>
>>> On reading, MagicNumber and the max id are set properly. Then I try to
>>> read the data into a QVector<Token> tokenVec:
>>>
>>> in>> tokenVec;
>>>
>>>
>> Huh? You are writing the data away with a loop, but expect to be able
>> to read them back in one go into a QVector? That seems a bit
>> optimistic... QVector itself has a structure, as documentented in the
>> page "Format of the QDataStream Operators" in the documentation. It
>> first writes out a 32 bits unsigned integer with the number of
>> elements, and then the elements themselves. If you don't have that
>> number of elements writen out, how do you expect QVector to be able to
>> properly stream in the data?
>>
> I thought it would be something like: »read as much Token as possible
> from stream and put them in the vector«. Obviously, that was a wrong
> assumption :)
>
Obviously :-)
Remember, there is nothing magical about QDataStream. It is reading and
writing some binairy data, but it does not know anything about it's
format that you did not tell it explicitly. Any byte in the stream is
taking to mean exactly what you tell QDataStream it means. Also, the
reading code knows nothing about the writing code. That means that you
need to read it back exactly the way you wrote it out. So, you need to
be very careful to keep your reading and your writing code symetrical.
Also, you need to know what you expect in the datafile, and how much of
it. That means for instance, that for every list you write out, you need
to write out how many elements are in that list, and then be sure that
you actually read that many elements. That is exactly what Qt is doing.
So, it requires precision. It awards you with fast write-out and
readback, and small files.
>> Is token.unique actually a quint32? You stream it out as one, but I
>> can not see if is streamed in properly based on this code.
>>
> No, it is an ordinary int, and it seems to cause problems. (I thought
> there would be an implicit cast from quint32 to int, but I seem to be
> wrong again.)
As I said above: you need to read back exactly what you wrote out. If
you write out a quint32, you need to read back the same data type. The
cast you as for does happen, but int is not casted to quint32, but (I
guess) to qint32. Note the missing 'u' there. Having said that: why
isn't token.unique a quint32 in the first place? Are you using negative
identifiers?
Also, I find that it is a good idea to use Qt's explicit data types when
you work with binairy files. The size of an int is not constant between
systems, for instance. What do you expect to happen when you read in an
int on a 32 bits machine from a file that was created on a 64 bits
machine? If you are lucky, they agree on the size of int. If you are
unlucky, then you are reading back only half of what was written out,
and the next thing you read ends up being trash.
> Unfortunately, I can't get it work, even if I do an
> explicit cast. Here's what class Token now looks like and how the
> operators are defined:
>
>
On first inspection, I don't see any obvious mistakes. Best is to do a
bit of trying out. Write out your file, and open it with a binairy
editor so you can inspect the data inside. There is a very nice on in
KDE that can handle Qt data types, if you need it. You can then inspect
if the data actually looks like what you expect it to be. Perhaps start
with writing out and reading back a single Token object.
André
More information about the Qt-interest-old
mailing list