Important: Please read the Qt Code of Conduct -

[SOLVED] QNetworkReply - best practices

  • Currently, I am using the SIGNAL readyRead() on my QNetworkReply object. I realized that sometimes there is still more data and readyRead() is called multiple time (for example when receiving a big xml file from my web service)

    Is there a difference from using the SIGNAL finished() on the QNetworkReply object? For me it would be easier, since I know all the data is ready with finished(), with readyRead(), how do I know if there is more data coming? Also, is using finished() bad practice, I may have to read a lot of xml data, would readyRead() be better for performance? as it read data when is it available? If so, my main question is how to know when the data transfer is complete, do I have to check if finished() has been triggered each loop of readyRead() or is there an easier way, thank you!

    Code sample :

    @void Main_WorkoutPage::on_pushButton_checkDB_clicked() {

    const QString url = "---- (erased for privacy)";
    QNetworkRequest request;
    request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
    replyGetWorkoutList = manager->get(request);
    connect(replyGetWorkoutList, SIGNAL(readyRead()), this, SLOT(slotReadyReadWorkoutList()));
    connect(replyGetWorkoutList, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotErrorWorkoutList(QNetworkReply::NetworkError)));
    connect(replyGetWorkoutList, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrorsWorkoutList(QList<QSslError>)));
    connect(replyGetWorkoutList, SIGNAL(finished()), this, SLOT(testSlotFinished()) ) ;


    void Main_WorkoutPage::testSlotFinished() {

    qDebug() << "OK SLOT FINISHED!";
    QByteArray arrayData =  replyGetWorkoutList->readAll();
    qDebug() << arrayData;


  • Moderators


    [quote]is using finished() bad practice, I may have to read a lot of xml data, would readyRead() be better for performance?[/quote]
    I guess it depends on how much data you are downloading. If the data is small enough to fit in your RAM, connecting to QNetworkReply::finished() and then calling QNetworkReply::readAll() is a good solution.

    With XML data though, you can attach your QNetworkReply to a QXmlStreamReader. The reader can handle data that arrives in multiple chunks.

    [quote]with readyRead(), how do I know if there is more data coming?[/quote]

  • Here is an example of xml file I get, this one has 5 intervals

    I guess this one is small enought to fit in the RAM, i'll have to check with bigger file later, it could grow to 200-1000 intervals, maybe writing the xml file to disk with readyRead() or another solution could be better when this arrive, thanks!

  • Just a note, I found the perfect solution in "qt doc":

    bq. Incremental parsing
    QXmlStreamReader is an incremental parser. It can handle the case where the document can't be parsed all at once because it arrives in chunks (e.g. from multiple files, or over a network connection). When the reader runs out of data before the complete document has been parsed, it reports a PrematureEndOfDocumentError. When more data arrives, either because of a call to addData() or because more data is available through the network device(), the reader recovers from the PrematureEndOfDocumentError error and continues parsing the new data with the next call to readNext().
    For example, if your application reads data from the network using a network access manager, you would issue a network request to the manager and receive a network reply in return. Since a QNetworkReply is a QIODevice, you connect its readyRead() signal to a custom slot, e.g. slotReadyRead() in the code snippet shown in the discussion for QNetworkAccessManager. In this slot, you read all available data with readAll() and pass it to the XML stream reader using addData(). Then you call your custom parsing function that reads the XML events from the reader.

Log in to reply