Get each line of QProcess output



  • I need to parse perl script output text by lines.
    Example of code:
    I start my script like this:
    @QProcess *proc->start("perl",args); // args - is QStringList
    connect(proc,SIGNAL(readyReadStandardOutput()),this,SLOT(readyRead()));@
    then get output:
    @void readyRead()
    {
    qDebug()<<proc->readAllStandardOutput();
    }@
    But i get all output at once or separated for some parts.
    I need to get output by lines, like in usual console (Konsole, gnome-terminal, tty etc.).
    How can I do this?



  • As [[Doc:QProcess]] is a [[Doc:QIODevice]] subclass, you can use readLine() on the standard output of your perl script.



  • Tried this, but it work not as I expected.
    @proc->start("perl",args);
    proc->waitForFinished(); // didn't work without this

    QTextStream stream(proc);
    while (!stream.atEnd()) {
    qDebug()<<stream.readLine();
    }@
    Lines shows only after process ends, but I want to see lines in realtime.



  • QIODevice emits the readyRead ( QProcess in addition readyReadStandardOutput and readyReadStandardError) signal whenever there is new data available.



  • I know. But as I said: it didn't shows output by lines.


  • Moderators

    You wait until the process is finished before you start to read the lines.


  • Moderators

    This could be closer to what you are looking for.
    @proc->start("perl",args);
    // proc->waitForFinished(); // didn't work without this

    QTextStream stream(proc);
    while (proc->state() == QProcess::Running) {
    qDebug()<<stream.readLine();
    }@

    Beware, I have not tested this. You may run into problems, when the state is still "starting". Furthermore, it is not clear to me what happens if there is no information to be read.
    Another option would be to use the different signals as suggested by Lukas.



  • I know. As I said, without waitForFinished() it didn't work. But works in diferent thread (not main/GUI thread).

    My english not so good to explain the problem, so here a code example to show a problem:
    @int lines = 0;
    void MyThread::readyRead() // slot for readyReadStandardOutput()
    {
    QTextStream stream(proc); // proc - is QProcess
    QString line;
    do {
    line = stream.readLine();
    emit newText(line); // adds line to QTextBrowser
    // qDebug()<<line;
    } while (!line.isNull());
    qDebug()<<lines++;
    }@
    This code reads perl script output.
    Then, when all done, I get lines count in QTextBrowser.
    In my case it's ~1000 of lines, but "lines" variable has value 15!
    So readyReadStandardOutput() emited only 15 times, not 1000.
    This is my problem.

    Sorry for bad english.



  • Sounds like your perl application isn't flushing the output buffer.



  • QProcess::waitForFinished() blocks your application, thus no event processing happens. This means if you use QProcess::waitForFinished() you cannot use the readyRead* signals (as signals require event processing). You either use the synchronous API (waitForFinished()) or the asynchronous API (signals) - you (usually) cannot mix both. One exception is if you are blocking a secondary thread (as in your case) instead of the event-processing thread.

    In most cases you do not want to use QProcess::waitForFinished(), least of all in your GUI thread as this would block the user interface. Just connect to the finished and readyRead* signals. This way you do not need a secondary thread too.

    But - as Andre already mentioned - you can only read data if there is data available. And stdout is usually buffered until it is flushed or the application terminates.



  • In case stdout (of your perl process) is not attached to a terminal (which is the case with using QProcess), the output is usually buffered by 4026 byte blocks. In case the stdout is attached to a terminal, it is usually line bufferd, i.e. a flush is executed at last after every newline.

    To circumvent this, you will need to call flush manually or set the output to unbuffered in your perl script.

    @

    disable buffering

    $| = 1;
    @

    More info in the "perl cookbook":http://docstore.mik.ua/orelly/perl/cookbook/ch07_13.htm



  • Here you can find a possible workaround for the problem:
    http://msturm.p7.de/programming_qprocess.php


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.