[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