如何从 C++/Qt Linux 应用程序逐行读取 FIFO/命名管道?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3861948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I read a FIFO/named pipe line by line from a C++/Qt Linux app?
提问by Johan
How do I read a FIFO/named pipe line by line from a C++/Qt Linux app?
如何从 C++/Qt Linux 应用程序逐行读取 FIFO/命名管道?
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.
今天我可以从Qt程序的fifo中打开并读取,但我无法让程序逐行读取数据。Qt 读取整个文件,这意味着他一直等到“发送者”关闭他的会话。
Let's take a example with some shell commands to show what I would like the app to do.
让我们举一个例子,用一些 shell 命令来展示我希望应用程序做什么。
First create a fifo
首先创建一个fifo
mkfifo MyPipe
Then we can use cat to read from the fifo
然后我们可以使用 cat 从 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.
然后开始输入一些东西,每次按回车键都会到达阅读器。然后当你用 Ctrl+D 关闭它时,两边都结束。
Now the sender is easy to create with a QTextStream, you just need to flush when you want to send.
现在发送者很容易用 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();
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.
但是然后写一个逐行读取的小读者是我现在卡住的地方,我对 Qt lib 的所有尝试最终都得到了数据,但直到发件人在 fifo 上使用 file.close() . 不是当他冲水时,就像我使用 cat 阅读时发生的那样。
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...
感觉就像我需要在流上使用某种 isReady 或 lineAvailable 或类似的东西,但我在文档中找不到任何适合的东西......
/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.
如果我使用低级 c 样式并在当时读取一个字符,我确实会得到我正在搜索的样式。但是能够做同样的 Qt 风格会很好。
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.
当我启动调试器时,程序挂在 readLine() 上,并且在对方关闭 fifo 之前不要继续。
And I do get the same using ">>"
而且我确实使用“>>”得到了相同的结果
line = in.readLine();
in >> line;
采纳答案by Johan
Use the low level c style and read one char at the time.
使用低级 c 样式并一次读取一个字符。
FILE *fp;
fp=fopen("MyPipe", "r");
char c;
while((c=getc(fp)) != EOF)
{
printf("%c",c);
}
fclose(fp);
回答by shodanex
I don't know what does not work but you can try to debug it using strace:
我不知道什么不起作用,但您可以尝试使用 strace 调试它:
strace -o writer.log -e trace=write ./writer
strace -o reader.log -e trace=read ./reader
The first line will log all the write system call made by your writer program. The second line works in a similar fashion. This way you can trace the system call, and be sure that your flushing works.
第一行将记录您的 writer 程序进行的所有 write 系统调用。第二行以类似的方式工作。这样您就可以跟踪系统调用,并确保您的刷新工作正常。
If you see repeated call to read, with the correct timing and data, then you have a problem with QTextStream.
如果您看到重复的 read 调用,具有正确的时间和数据,那么您的 QTextStream 有问题。
What happens if you don't use a QTextStream, but directly read from the file ?
如果不使用 QTextStream,而是直接从文件中读取会发生什么?
回答by Edgar Bonet
You could try to open the file on the reader side with the QIODevice::Unbuffered
flag.
您可以尝试在阅读器端打开带有QIODevice::Unbuffered
标志的文件。
回答by Yogi Joshi
if(file.bytesAvailable())
QString line = file.readLine();
You could use something like this.
你可以使用这样的东西。