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

发布于 2024-09-26 06:56:29 字数 1673 浏览 7 评论 0原文

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

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

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

首先创建一个fifo

mkfifo MyPipe

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

cat MyPipe 

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

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 库的所有尝试最终都得到了数据,但是 直到发送方在 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 风格并在我这样做时读取一个字符 找到我正在寻找的风格。 但如果能够实现相同的 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;

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

﹉夏雨初晴づ 2024-10-03 06:56:29

使用低级c风格并一次读取一个字符。

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

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);
つ可否回来 2024-10-03 06:56:29

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

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

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

如果您看到重复调用 read 且时间和数据正确,则 QTextStream 存在问题。

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

I don't know what does not work but you can try to debug it using 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.

If you see repeated call to read, with the correct timing and data, then you have a problem with QTextStream.

What happens if you don't use a QTextStream, but directly read from the file ?

囚你心 2024-10-03 06:56:29
if(file.bytesAvailable())
QString line = file.readLine();

你可以使用这样的东西。

if(file.bytesAvailable())
QString line = file.readLine();

You could use something like this.

不再见 2024-10-03 06:56:29

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

You could try to open the file on the reader side with the QIODevice::Unbuffered flag.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文