How do I read a FIFO/named pipe line by line from a C++/Qt Linux app?

Johan picture Johan · Oct 5, 2010 · Viewed 15.3k times · Source

How do I read a FIFO/named pipe line by line from a C++/Qt Linux app?

Today I can open and read from a fifo from a Qt program, but I can't get the program to read the data line by line. Qt reads the entire file, meaning he waits until the "sender" closes his session.

Let's take a example with some shell commands to show what I would like the app to do.

First create a fifo

mkfifo MyPipe

Then we can use cat to read from the fifo

cat MyPipe 

And then we send some data in with another cat

cat > MyPipe

And then start to type something, and every time you hit enter it arrives at the reader. And then when you close it with Ctrl+D both sides end.

Now the sender is easy to create with a QTextStream, you just need to flush when you want to send.

QFile file("MyPipe");
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    return;

QTextStream out(&file);
for(int i=0; i<3; i++) {
    out << "Hello...: " << i << "\n";
    out.flush();
    sleep(2);
}

file.close();

But then to write a little reader that read line by line is where I'm stuck right now, all my tries with the Qt lib ends up with that I get the data but not until the sender uses file.close() on the fifo. Not when he flush, as occurs when I use cat to read.

Like this example:

QFile file("MyPipe");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    return 0;

QTextStream in(&file);
QString line;
do {
    line = in.readLine();
    qDebug() << line;
} while (!in.atEnd());


file.close();

What am I missing?

It just feels like I need to use some kind of isReady or lineAvailable on the stream or something like that, but I can't find anything in the docs that fits...

/Thanks


Note:

If I go with the low level c style and read one char at the time I do get the style Im searching for. But it would be nice to be able to do the same Qt style.

FILE *fp;
fp=fopen("MyPipe", "r");
char c;
while((c=getc(fp)) != EOF)
{
    printf("%c",c);
}
fclose(fp);

Update:

When I start a debugger the program is hanging on the readLine(), and do not continue until the other party closes the fifo.

And I do get the same using ">>"

    line = in.readLine();
    in >> line;

Answer

Johan picture Johan · Oct 30, 2010

Use the low level c style and read one char at the time.

FILE *fp;
fp=fopen("MyPipe", "r");
char c;
while((c=getc(fp)) != EOF)
{
    printf("%c",c);
}
fclose(fp);