Как построчно читать FIFO / именованный конвейер из приложения C ++ / Qt Linux? - PullRequest
6 голосов
/ 05 октября 2010

Как читать строку FIFO / именованный конвейер построчно из приложения C ++ / Qt Linux?

Сегодня я могу открывать и читать из fifo из программы Qt, но я не могу заставить программу читать данные построчно. Qt читает весь файл, то есть он ждет, пока «отправитель» закроет свой сеанс.

Давайте рассмотрим пример с некоторыми командами оболочки, чтобы показать, что бы я хотел, чтобы приложение делало.

Сначала создайте fifo

mkfifo MyPipe

Тогда мы можем использовать cat для чтения с fifo

cat MyPipe 

А потом мы отправляем некоторые данные другому коту

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 заканчиваются тем, что я получаю данные, но пока отправитель не использует file.close () на fifo. Не когда он смывает, как это происходит, когда я читаю с помощью кошки.

Как в этом примере:

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 on поток или что-то в этом роде, но я не могу найти в документах ничего подходящего ...

/ Спасибо


Примечание :

Если я перейду к низкоуровневому стилю 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;

Ответы [ 4 ]

4 голосов
/ 31 октября 2010

Используйте стиль низкого уровня c и читайте один символ за раз.

FILE *fp;
fp=fopen("MyPipe", "r");
char c;
while((c=getc(fp)) != EOF)
{
    printf("%c",c);
}
fclose(fp);
2 голосов
/ 28 октября 2013
if(file.bytesAvailable())
QString line = file.readLine();

Вы можете использовать что-то вроде этого.

2 голосов
/ 05 октября 2010

Я не знаю, что не работает, но вы можете попробовать отладить его, используя strace:

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

В первой строке будут записываться все системные вызовы write, сделанные вашей программой-писателем.Вторая линия работает аналогичным образом.Таким образом, вы можете отследить системный вызов и быть уверенным, что ваш сброс работает.

Если вы видите повторный вызов для чтения с правильной синхронизацией и данными, то у вас проблема с QTextStream.

Что произойдет, если вы не используете QTextStream, а непосредственно читаете из файла?

1 голос
/ 05 октября 2010

Вы можете попытаться открыть файл на стороне считывателя с флагом QIODevice::Unbuffered.

...