Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QVector serialization / deserialization



  • Hi,

    I have a Qvector :

    struct enrolment {
            QString person_name;
            QPixmap person_foto;
            QString category;
        };
    
    QVector<enrolment> enrolment_db;
    

    And populating the enrolment_db vector around 1000 item.

    I want to save file and get back from file to QVector again.

    I tried:

    QFile personel_file("/data/personelVec.dat");
            personel_file.open(QIODevice::WriteOnly);
            QDataStream out_personelVec(&personel_file);   // we will serialize the data into the file
            out_personelVec.setVersion(QDataStream::Qt_5_10);
            out_personelVec << enrolment_Db;
    

    for serialization but gives error.

     invalid operands to binary expression ('QDataStream' and 'const typename QVector<enrolment>::value_type' (aka 'const enrolment'))
    

    What is the proper way to serialize / deserialize such QVector<enrolment> enrolment_db . ?

    examole appreciated.

    Best


  • Lifetime Qt Champion

    Hi,

    You have implement the QDataStream operators for your enrolment struct. See here.



  • struct enrolment {
            QString person_name;
            QPixmap person_foto;
            QString category;
        };
    QFile file ("/data/personel.ser");
                QDataStream & operator<< (QDataStream& stream, const enrolment& enrolment);
                
                QDataStream out(&file);
                out.setVersion(QDataStream::Qt_5_10);
                out << enrolment_Db;
    

    is this the way ?


  • Lifetime Qt Champion

    Since I don't know where you put what in your source tree I can't say yes for sure.



  • I searched the internet and couldn't find a similar working example .

    if somebody kindly make an example it could be useful for new beginners.

    struct enrolment {
            QString person_name;
            QPixmap person_foto;
            QString category;
        };
    
        QVector <enrolment> enrolment_Db;
    
    //add 1000 item to the enrolment_Db
    
    serialize  enrolment_Db to file
    deserilaize from file.
    

    I am lack of QDatastream deep knowledge. appreciated for example.


  • Lifetime Qt Champion

    Hi
    Lucky its not super complex.

    in .h file
    struct enrolment {
      QString person_name;
      QPixmap person_foto;
      QString category;
    };
    
    QDataStream& operator <<(QDataStream& out, const enrolment Entry);
    QDataStream& operator >>(QDataStream& in, enrolment Entry);
    

    and in .cpp

    // save
    QDataStream& operator <<(QDataStream& out, const enrolment Entry) {
       out << Entry.person_name;
      out << Entry.person_foto;
      out << Entry.category;
      return out;
    }
    
    // load. MUST BE SAME ORDER as when saved
    QDataStream& operator >>(QDataStream& in, enrolment &Entry) { 
      in >> Entry.person_name;
      in >> Entry.person_foto;
      in >> Entry.category;
      return in;
    }
    


  • it gave:

    error: overloaded 'operator<<' must be a binary operator (has 3 parameters)
        QDataStream& operator <<(QDataStream& out, const enrolment Entry);
    

    for

    QDataStream& operator <<(QDataStream& out, const enrolment Entry);
    QDataStream& operator >>(QDataStream& in, enrolment &Entry);
    

  • Lifetime Qt Champion

    @RahibeMeryem
    Can you show the actual code ?
    My compiler had zero issues.

    That errors come if you put them inside class. like with friend.
    did you add just like in sample ?
    under class?



  • I put the private section of the header below :

    in widget.h file
    struct enrolment {
      QString person_name;
      QPixmap person_foto;
      QString category;
    };
    
    QDataStream& operator <<(QDataStream& out, const enrolment Entry);
    QDataStream& operator >>(QDataStream& in, enrolment &Entry);
    
    

    in the widget.cpp :

    void Widget::on_select_folder_enrolment_clicked()
    {
     // save
    QDataStream& operator <<(QDataStream& out, const enrolment Entry) {
       out << Entry.person_name;
      out << Entry.person_foto;
      out << Entry.category;
      return out;
    }
    
    // load. MUST BE SAME ORDER as when saved
    QDataStream& operator >>(QDataStream& in, enrolment &Entry) { 
      in >> Entry.person_name;
      in >> Entry.person_foto;
      in >> Entry.category;
      return in;
    }
    ....
    ....
    
    
    
    

  • Lifetime Qt Champion

    @RahibeMeryem

    ohhh o.O
    Ok. do not put them inside the functions.
    have them outside as a function on its own.
    it allows you to do

    QFile personel_file("/data/personelVec.dat");
            personel_file.open(QIODevice::WriteOnly);
            QDataStream out_personelVec(&personel_file);   // we will serialize the data into the file
            out_personelVec.setVersion(QDataStream::Qt_5_10);
            out_personelVec << enrolment_Db;
    

    as you tried before as we now gave it a << to be used
    out_personelVec << enrolment_Db;

    so its

    
    QDataStream& operator <<(QDataStream& out, const enrolment Entry) {
    ... not showing code. but dont delete !
    }
    
    QDataStream& operator >>(QDataStream& in, enrolment &Entry) { 
    ...
    }
    
    
    void Widget::on_select_folder_enrolment_clicked()
    {
    QFile personel_file("/data/personelVec.dat");
            personel_file.open(QIODevice::WriteOnly);
            QDataStream out_personelVec(&personel_file);   // we will serialize the data into the file
            out_personelVec.setVersion(QDataStream::Qt_5_10);
            out_personelVec << enrolment_Db;
    }
    


  • :))

    Thanks a lot .. I am math and deep learning expert.. most of the my time spending non main subject related struggling like this.

    Qt is Wonderfull but needs deep knowledge and operational expertise which is require time and facing problems.

    Best


  • Lifetime Qt Champion

    @RahibeMeryem
    well operator overloading ( << and >> are operators ) is somewhat
    intermediate level.

    Just for the fullness of this post.

    You could have done
    out_personelVec << enrolment_Db. person_name << enrolment_Db. person_foto ;
    since it know how to stream QString and pixmap already.

    However, the operator overloading is smart if you later do
    struct SomeOther {
    enrolment en;
    };

    if you then overload for "SomeOther"
    then
    SomeOther test;
    out << test;
    will just work as it calls << for enrolment
    so it allows for deep nesting of Types, each with the ability to save it self.


  • Lifetime Qt Champion

    One small thing, it should be:

    QDataStream& operator >>(QDataStream& in, enrolment& Entry);
    

    Otherwise there's no way to get the data back in the caller function.


  • Lifetime Qt Champion

    @SGaist
    Good catch. Thank you. Updated sample.
    and remember to change both in .h and in .cpp. (RahibeMeryem)



  • Serialization is ok ;

    deserialization gives below error:

    /Users/alpullu/Qt/5.11.0/clang_64/lib/QtCore.framework/Headers/qdatastream.h:243: error: use of overloaded operator '>>' is ambiguous (with operand types 'QDataStream' and 'typename QVector<enrolment_>::value_type' (aka 'enrolment_'))
            s >> t;
            ~ ^  ~
    
    // load. MUST BE SAME ORDER as when saved
    QDataStream& operator >>(QDataStream& in, enrolment_& Entry) {
      in >> Entry.person_name;
      in >> Entry.person_foto;
      in >> Entry.category;
      in >> Entry.face_indexed_status;
      return in;
    }
    

  • Lifetime Qt Champion

    @RahibeMeryem

    Please always show code as you being unused to Qt / c++ might
    give situation where you did something in code we would never think of.



  • I exactly copied your deserialization example :

    // load. MUST BE SAME ORDER as when saved
    QDataStream& operator >>(QDataStream& in, enrolment_& Entry) {
      in >> Entry.person_name;
      in >> Entry.person_foto;
      in >> Entry.category;
      in >> Entry.face_indexed_status;
      return in;
    }
    
    honestly didnt understand why its not working . :(
    
     
    

  • Lifetime Qt Champion

    @RahibeMeryem
    hi
    but does the error point to this ?
    I assumed it was where you used it.
    as in where you try to load in the file again.
    Can you show that code ?



  • the error is in this line : in_personelVec >> enrolment_Db;
    gives:
    /Users/xx/Qt/5.11.0/clang_64/lib/QtCore.framework/Headers/qdatastream.h:243: error: use of overloaded operator '>>' is ambiguous (with operand types 'QDataStream' and 'typename QVector<enrolment_>::value_type' (aka 'enrolment_'))
    s >> t;
    ~ ^ ~

    void Widget::load_enrollment_if_exist()
    {
        bool fileExists = QFileInfo::exists(enrollment_path) && QFileInfo(enrollment_path).isFile();
        if (fileExists){
            QFile personel_file(enrollment_path);
                    personel_file.open(QIODevice::ReadOnly);
                    QDataStream in_personelVec(&personel_file);   // we will deserialize the data into the file
                    in_personelVec.setVersion(QDataStream::Qt_5_10);
                    in_personelVec >>  enrolment_Db;  ///////////THE ERROR is HERE
                    qDebug() << " enrolment yüklendi: , personel sayısı: " << enrolment_Db.size()  ;
        }
    
    }
    
    // save
    QDataStream& operator <<(QDataStream& out, const enrolment_ Entry) {
      out << Entry.person_name;
      out << Entry.person_foto;
      out << Entry.category;
      out << Entry.face_indexed_status;
      return out;
    }
    
    // load. MUST BE SAME ORDER as when saved
    QDataStream& operator >>(QDataStream& in, enrolment_& Entry) {
      in >> Entry.person_name;
      in >> Entry.person_foto;
      in >> Entry.category;
      in >> Entry.face_indexed_status;
      return in;
    }
    


  • Do we need to write QVector<enrolment_> size ? because it has 1000 elements ?


  • Lifetime Qt Champion

    What type is Entry.face_indexed_status ?

    No you don't have to do anything, QVector is already a supported type so as long you provide the data stream operator for your class you're good.

    Note that again, you have to handle that properly in your code, meaning that if you stream something, then your vector then something else, in your read code you have to again do that in the same order.



  • in the header :

    struct enrolment_ {
    QString person_name;
    QPixmap person_foto;
    QString category;
    QString file;
    QString face_indexed_status;
    };

    QDataStream& operator <<(QDataStream& out, const enrolment_ Entry);
    QDataStream& operator >>(QDataStream& in, enrolment_ Entry);


  • Lifetime Qt Champion

    @RahibeMeryem

    Did you add the missing & to BOTH .h and cpp ?
    seems to be missing in .h
    QDataStream& operator >>(QDataStream& in, enrolment_ & Entry); // NOTE the &

    please check u changed in both places.



  • Finally I figured it out ... to find that I missed '&' . in .h . took half day with 250 litre coffee :)))

    But I want to thanks you all Gentlemen...

    Really this is the best and useful answer for me all my Qt adventure

    THANKS
    THANKS..
    0_1541342863330_eda44b14-6526-4720-893a-23f408e590b4-image.png


  • Lifetime Qt Champion

    @RahibeMeryem
    Super!
    The good part being - this is the way for all classes you make.
    So you now can stream anything you like.



  • Now I have implemented with QList struct, a issue is QDataStream only support for me QString values otherwise (with numbers) only read a part of information. this works for me.

    QDataStream& operator << (QDataStream& out, const anualxls Entry) {
    out << QString::number(Entry.anio);
    out << QString::number(Entry.suma,'f');
    out << QString::number(Entry.sumawo,'f' );
    out << QString::number(Entry.tasa, 'f') ;
    out << QString::number(Entry.tasawo, 'f');

    qDebug() << "Escribiendo " << Entry.anio << Entry.suma << Entry.tasa;

    return out;
    }

    // load. MUST BE SAME ORDER as when saved
    QDataStream& operator >>(QDataStream& in, anualxls &Entry) {
    QString temp;
    in >> temp; Entry.anio = temp.toInt();
    in >> temp; Entry.suma = temp.toFloat();
    in >> temp; Entry.sumawo = temp.toFloat();
    in >> temp; Entry.tasa = temp.toFloat();
    in >> temp; Entry.tasawo = temp.toFloat();
    qDebug() << "Leyendo " << Entry.anio << Entry.suma << Entry.tasa;
    return in;
    }


  • Lifetime Qt Champion

    @eangeli__ said in QVector serialization / deserialization:

    a issue is QDataStream only support for me QString values otherwise (with numbers) only read a part of informatio

    How did you do it with numbers? It should work.


Log in to reply