6

如何从 C++/Qt Linux 应用程序中逐行读取 FIFO/命名管道?

今天我可以从 Qt 程序中打开并读取 fifo,但我无法让程序逐行读取数据。Qt 读取整个文件,这意味着他等到“发送者”关闭他的会话。

让我们以一些 shell 命令为例来展示我希望应用程序执行的操作。

首先创建一个fifo

mkfifo MyPipe

然后我们可以使用 cat 从 fifo 中读取

cat MyPipe 

然后我们用另一只猫发送一些数据

cat > MyPipe

然后开始输入一些东西,每次你敲回车时它都会到达阅读器。然后当你用 Ctrl+D 关闭它时,两边都会结束。

现在发送者很容易用 QTextStream 创建,你只需要在你想发送的时候刷新。

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();

但是然后写一个逐行读取的小阅读器是我现在卡住的地方,我对Qt lib的所有尝试最终都得到了数据,但直到发件人在fifo上使用file.close() . 不是当他冲洗时,就像我使用 cat 阅读时发生的那样。

像这个例子:

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();

我错过了什么?

感觉就像我需要在流上使用某种 isReady 或 lineAvailable 或类似的东西,但我在文档中找不到任何适合...

/谢谢


注意

如果我使用低级 c 风格并在当时阅读一个字符,我确实得到了我正在寻找的风格。但是能够做同样的 Qt 风格会很好。

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

更新

当我启动调试器时,程序挂在 readLine() 上,直到对方关闭 fifo 才继续。

我确实使用“>>”得到了同样的结果

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

4 回答 4

4

使用低级 c 样式并一次读取一个字符。

FILE *fp;
fp=fopen("MyPipe", "r");
char c;
while((c=getc(fp)) != EOF)
{
    printf("%c",c);
}
fclose(fp);
于 2010-10-30T20:49:18.600 回答
2

我不知道什么不起作用,但您可以尝试使用 strace 对其进行调试:

strace -o writer.log -e trace=write ./writer 
strace -o reader.log -e trace=read ./reader 

第一行将记录您的 writer 程序进行的所有 write 系统调用。第二行以类似的方式工作。这样您就可以跟踪系统调用,并确保您的刷新工作正常。

如果您看到重复调用读取,并且具有正确的时间和数据,那么您的 QTextStream 有问题。

如果您不使用 QTextStream,而是直接从文件中读取会发生什么?

于 2010-10-05T10:54:58.690 回答
2
if(file.bytesAvailable())
QString line = file.readLine();

你可以使用这样的东西。

于 2013-10-28T00:56:01.520 回答
1

您可以尝试使用QIODevice::Unbuffered标志在阅读器端打开文件。

于 2010-10-05T14:55:05.210 回答