Get each line of QProcess output
-
wrote on 5 Nov 2011, 23:03 last edited by
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? -
wrote on 6 Nov 2011, 00:48 last edited by
As [[Doc:QProcess]] is a [[Doc:QIODevice]] subclass, you can use readLine() on the standard output of your perl script.
-
wrote on 6 Nov 2011, 14:48 last edited by
Tried this, but it work not as I expected.
@proc->start("perl",args);
proc->waitForFinished(); // didn't work without thisQTextStream stream(proc);
while (!stream.atEnd()) {
qDebug()<<stream.readLine();
}@
Lines shows only after process ends, but I want to see lines in realtime. -
wrote on 6 Nov 2011, 14:58 last edited by
QIODevice emits the readyRead ( QProcess in addition readyReadStandardOutput and readyReadStandardError) signal whenever there is new data available.
-
wrote on 6 Nov 2011, 15:38 last edited by
I know. But as I said: it didn't shows output by lines.
-
wrote on 6 Nov 2011, 17:19 last edited by
You wait until the process is finished before you start to read the lines.
-
wrote on 6 Nov 2011, 17:23 last edited by
This could be closer to what you are looking for.
@proc->start("perl",args);
// proc->waitForFinished(); // didn't work without thisQTextStream 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. -
wrote on 6 Nov 2011, 17:35 last edited by
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.
-
wrote on 6 Nov 2011, 17:37 last edited by
Sounds like your perl application isn't flushing the output buffer.
-
wrote on 6 Nov 2011, 19:17 last edited by
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.
-
wrote on 6 Nov 2011, 23:15 last edited by
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
-
wrote on 15 Jun 2013, 11:14 last edited by
Here you can find a possible workaround for the problem:
http://msturm.p7.de/programming_qprocess.php