Tail-f function in qt
-
-
This is the code...dont know what i am doing wrong
@#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX 512int main()
{
int fd;
char * myfifo = "myfifo";/* create the FIFO (named pipe) */ mkfifo(myfifo, 0666); /* write to the FIFO */ open(myfifo, O_WRONLY);
FILE *file, *file2;
char line[MAX];file = fopen("alert.csv", "r");
//file2 = fopen(myfifo, "w");
while (fgets(line,sizeof(line),file) != NULL)
{
/*Write the line */
fputs(line, myfifo);
printf(line);}
fclose (file);
// fclose (file2);
unlink(myfifo);
close(fd);
return 0;
}
@ -
If you just run a process as a QProcess and need to get its output you could also just have it print to stdout and use QProcess' methods to access the output.
-
After you create the fifo, you open it like its a file, then it works.
Your app modified;
@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX 512int main() { int fd; char * myfifo = "myfifo"; /* create the FIFO (named pipe) */ mkfifo(myfifo, 0666); /* write to the FIFO */ open(myfifo, O_WRONLY); FILE *file, *file2; char line[MAX]; file = fopen("alert.csv", "r"); file2 = fopen(myfifo, "w"); while (fgets(line,sizeof(line),file) != NULL) { /*Write the line */ fputs(line, file2); printf(line); } fclose (file); // fclose (file2); unlink(myfifo); close(fd); return 0; }
@
Naturally, its a pipe, a first-in-first-out pipe.
If you put stuff in but nobody is on the other side to read it, it will soon stop being able to take more in.So start a second shell and type
tail -f myfifo
directly after your app started. -
Dear Thomas
My gui app is unable to get the contents from the fifo file...even though starting simultaneously...
The below code is to write to fifo file
@ #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX 512int main() { int fd; char * myfifo = "myfifo"; /* create the FIFO (named pipe) */ mkfifo(myfifo, 0666); /* write to the FIFO */ open(myfifo, O_WRONLY); FILE *file, *file2; char line[MAX]; file = fopen("alert.csv", "r"); file2 = fopen(myfifo, "w"); while (fgets(line,sizeof(line),file) != NULL) { /*Write the line */ fputs(line, file2); printf(line); } fclose (file); // fclose (file2); unlink(myfifo); close(fd); return 0; }@
The below code is to display the contents from the fifo file
@#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QtGui"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
QTableWidgetItem *item;
int row=0,column=0;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->alertshow->setColumnWidth(0,200);
ui->alertshow->setColumnWidth(1,250);
}MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::on_update_clicked()
{
QString line;
int fd;
char * myfifo = "/root/qt/untitled4/myfifo";/* create the FIFO (named pipe) */ //mkfifo(myfifo, 0666);
fd=mkfifo(myfifo, S_IFIFO | 0666);
//qDebug()<<fd;
/* write to the FIFO */
open(myfifo, O_RDONLY);
//qDebug()<<fd;QFile file2(myfifo); file2.open(QIODevice::ReadOnly | QIODevice::Text); QTextStream in(&file2); while (!in.atEnd()) { qDebug()<<"inside while"; line = in.readLine(); qDebug()<<line; QString delimiterPattern(","); QStringList fonts = line.split(delimiterPattern); qDebug() << fonts;
display(fonts);
// row++;
file2.close();} qDebug()<<"outside";
}
void MainWindow::display(QStringList list)
{
for(int i=0;i<list.count();i++){
//i++;
// qDebug()<<i;
QString li=list[i];item=new QTableWidgetItem(li);
ui->alertshow->setItem(row,column,item);
column++;
}
}@ -
Your beginning idea was that you want to update whenever something new is written by the first program.
A fifo can do that, but indeed its a bit tricky.
The basic concept behind the fifo is that its blocking. So your code that reads from the fifo will never return. Not untill you delete the fifo, at least.As such you likely want to run the read in a different thread and make it notify the main gui thread whenever a new line was successfully read.
It also means you never close the file. -
Hi Thomas...
fifo was giving some problems..so used pipe...in terminal i open my gui executable with tail command.
i.e tail -f alert.csv | ./myguii am getting all the values in console using qdebug...but mygui is freezing and displaying nothing.... any idea?
@QTableWidgetItem *item;
int row=0,column=0;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->alertshow->setColumnWidth(0,200);
ui->alertshow->setColumnWidth(1,250);
}MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::on_update_clicked()
{
QString line;QTextStream in(stdin); do { qDebug()<<"inside while"; line = in.readLine(); qDebug()<<line; QString delimiterPattern(","); QStringList fonts = line.split(delimiterPattern); qDebug() <<"fonts"<< fonts; display(fonts); }while(!line.isNull()); qDebug()<<"outside";
}
void MainWindow::display(QStringList list)
{
for(int i=0;i<list.count();i++)
{QString li=list[i];
qDebug()<<"csv"<<li;
item=new QTableWidgetItem(li);
ui->alertshow->setItem(row,column,item);
column++;
}
}
@ -
Aren't you running the do while loop forever ?
Try with line.isEmpty(), IIRC "" is empty but not null.
Hope it helps
-
You switched to reading a pipe, but the actual problem is not with the fifo its that your method on_update_clicked() will never return.
What you may not realize is that this means that the painting system will never do anything anymore, since its waiting for the on_update_clicked method to finish.
So, I think the fifo was a great idea, I suggest using that again.
I realize that threads are not easy, so let me suggest a different approach that will work too.
You can modify your on_update_clicked to exit when there is no data to read. See QIODevice::canReadLine()If you get tired of pressing the button you might want to instead connect that slot up to the QIODevice::readyRead() signal from your input file.
GOod luck!
-
The below code is giving error...can you please help
@QTextStream in(stdin);
QObject::connect(in, SIGNAL(readyRead()), this, SLOT(readcsv()));@error: no matching function for call to 'MainWindow::connect(QTextStream&, const char [13], MainWindow* const, const char [11])'
-
QTextStream does not have a readyRead signal, QFile does (from QIODevice).
-
"qfile wont emit signals like qio":http://qt-project.org/doc/qt-4.8/qfile.html#signals
-
Right ! I forgot about that.
Did you have a look at QSocketNotifier ? It might be what you need to monitor a pipe on unix. -
thanks Sgaist
@ notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read);
connect(notifier, SIGNAL(activated(int)), this, SLOT(readcsv()));@and used repaint() function in readcsv function...now gui is showing the contents ..but gui is still freezed...
any possible solution -
Do you still have an infinite loop somewhere ?
-
hi sgaist...This is the code...only using while(!line.isEmpty());
have tried with isnull() also..but same
@void MainWindow::readcsv()
{
QString line;
//ui->alertshow->repaint();
qDebug()<<"in readcsv";
QTextStream in(stdin,QIODevice::ReadOnly);do { // ui->alertshow->repaint(); qDebug()<<"inside while"; line = in.readLine(); qDebug()<<line; QString delimiterPattern(","); QStringList fonts = line.split(delimiterPattern); qDebug() <<"fonts"<< fonts; display(fonts); }while(!line.isEmpty()); qDebug()<<"outside";
}
void MainWindow::display(QStringList list)
{
ui->alertshow->repaint();
for(int i=0;i<list.count();i++)
{QString li=list[i];
qDebug()<<"csv"<<li;
item=new QTableWidgetItem(li);
ui->alertshow->setItem(row,column,item);
column++;
}
// ui->alertshow->repaint();
}
@