如何从C ++ / Qt Linux应用程序逐行读取FIFO /命名管道?
今天,我可以打开Qt程序中的fifo并进行阅读,
但是我无法让程序逐行读取数据。
Qt读取整个文件,这意味着他要等到"发送方"关闭其会话。
让我们以一些shell命令为例,展示我希望应用程序执行的操作。
首先创建一个fifo
mkfifo MyPipe
然后我们可以用猫从fifo中读取
cat MyPipe
然后我们与另一只猫一起发送一些数据
cat > MyPipe
然后开始输入内容,每次您按Enter键,它就会到达阅读器。
然后,当您使用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 <
";
out.flush();
sleep(2);
}
file.close();
但是,然后写一个小小的阅读器,逐行阅读是我现在遇到的问题,
我对Qt lib的所有尝试最终都得到了数据,但是
直到发送者在fifo上使用file.close()。
不是在他脸红的时候,而是当我用猫来阅读时。
像这个例子:
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风格,并且在那时读了一个char,
得到我正在寻找的风格。
但是能够执行相同的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() << line;,但没有看到任何冲洗。
好点,没想到。
使用低级c样式并一次读取一个字符。
FILE *fp;
fp=fopen("MyPipe","r");
char c;
while((c=getc(fp)) != EOF)
{
printf("%c",c);
}
fclose(fp);
c必须为int,否则,如果char是无符号的(EOF是负整数(通常为-1)),则可能是无限循环。
if(file.bytesAvailable())
QString line = file.readLine();
您可以使用类似这样的东西。
bytesAvailable的QFile实现对特殊文件(包括命名管道)不起作用,实际上会使应用程序崩溃!
我不知道什么不起作用,但是您可以尝试使用strace对其进行调试:
strace -o writer.log -e trace=write ./writer
strace -o reader.log -e trace=read ./reader
第一行将记录您的编写器程序进行的所有写入系统调用。 第二行以类似的方式工作。
这样,您可以跟踪系统调用,并确保刷新工作正常。
如果您看到重复的调用以正确的时间和数据进行读取,则说明QTextStream存在问题。
如果您不使用QTextStream,而是直接从文件中读取,该怎么办?
strace很不错,我在另一个窗口中启动了" watch tail reader.log",我可以看到他确实获取了我发送给他的数据。
@Johan:您确定问题出在读者方面吗?
95%可以肯定,因为如果我将" Qt版本"替换为" C版本",则可以正常工作。
@Johan:也许QtextStream是可疑的
我已经编写了这段Qt代码,它创建了一个FIFO套接字并在其上阻塞以尝试读取内容...每当我写入此FIFO套接字时,写入syscall都会挂起,并且似乎什么也没到达。 同样的错误? codepad.org/uuN2GI5w
您可以尝试使用QIODevice::Unbuffered标志在阅读器端打开文件。
天哪,但还是一样:(