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() 。不是當他沖洗時,就像我用貓讀書時那樣。
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;
4 个解决方案
#1
4
Use the low level c style and read one char at the time.
使用低級c樣式並在當時讀取一個char。
FILE *fp;
fp=fopen("MyPipe", "r");
char c;
while((c=getc(fp)) != EOF)
{
printf("%c",c);
}
fclose(fp);
#2
2
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但直接從文件中讀取會發生什么?
#3
2
if(file.bytesAvailable())
QString line = file.readLine();
You could use something like this.
你可以使用這樣的東西。
#4
1
You could try to open the file on the reader side with the QIODevice::Unbuffered flag.
您可以嘗試使用QIODevice :: Unbuffered標志在閱讀器端打開文件。