【问题标题】:How do I read a FIFO/named pipe line by line from a C++/Qt Linux app?如何从 C++/Qt Linux 应用程序中逐行读取 FIFO/命名管道?
【发布时间】:2010-10-05 08:21:02
【问题描述】:

如何从 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 on 流或类似的东西, 但我在文档中找不到任何适合...

/谢谢


注意

如果我使用低级 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;

【问题讨论】:

  • 会不会是管道被立即读取了,实际上是屏幕输出被缓冲了?你使用了qDebug() &lt;&lt; line;,我没有看到任何冲洗。
  • 好点,没想到。

标签: c++ linux qt named-pipes fifo


【解决方案1】:

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

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

【讨论】:

  • c 必须是int 否则如果char 是无符号的(EOF 是负整数(通常是-1)),它可能是一个无限循环。
【解决方案2】:

我不知道什么不起作用,但你可以尝试使用 strace 调试它:

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

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

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

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

【讨论】:

  • strace 很好,我在另一个窗口中启动了“watch tail reader.log”,我可以看到他确实收到了我发送给他的数据。
  • 95% 肯定,因为如果我用“C 版本”替换“Qt 版本”,它就可以工作。
  • @Johan : 也许 QtextStream 是嫌疑人
  • 我已经编写了这段 Qt 代码,它创建了一个 FIFO 套接字并阻止它尝试读取内容...每当我写入这个 FIFO 套接字时,写入系统调用就会挂起,似乎什么也没有到达。同样的错误? codepad.org/uuN2GI5w
【解决方案3】:
if(file.bytesAvailable())
QString line = file.readLine();

你可以使用这样的东西。

【讨论】:

  • bytesAvailable 的 QFile 实现不适用于特殊文件,包括命名管道,实际上会使应用程序崩溃!
【解决方案4】:

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

【讨论】:

  • 上帝的想法,但还是一样:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多