Domanda

Come posso leggere una FIFO/named pipe riga per riga da un'app C++/Qt Linux?

Oggi posso aprire e leggere da un FIFO da un programma QT, ma non riesco a ottenere il programma per leggere la riga di dati per riga.Qt legge l'intero file, nel senso che attende finché il "mittente" non chiude la sessione.

Facciamo un esempio con alcuni comandi della shell per mostrare cosa vorrei che l'app facesse.

Per prima cosa crea un fifo

mkfifo MyPipe

Quindi possiamo usare cat per leggere dal fifo

cat MyPipe 

E poi inviamo alcuni dati con un altro gatto

cat > MyPipe

E poi inizia a digitare qualcosa, e ogni volta che premi invio arriva al lettore.E poi quando lo chiudi con Ctrl+D entrambi i lati finiscono.

Ora il mittente è facile da creare con un QtextStream, devi solo sciacquare quando si desidera inviare.

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();

Ma poi per scrivere un piccolo lettore che leggi riga per riga è dove sono bloccato in questo momento, tutti i miei tentativi con il QT Lib finiscono con quello che ottengo i dati ma non fino a quando il mittente non utilizza file.close () sul FIFO .Non quando arrossisce, come accade quando uso il gatto per leggere.

Come questo esempio:

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();

Cosa mi manca?

Mi sembra di dover usare una sorta di isready o lineavailable sul flusso o qualcosa del genere, ma non riesco a trovare nulla nei dottori che si adatta ...

/Grazie


Nota:

Se vado con lo stile c di basso livello e leggo un carattere alla volta, lo faccio ottenere lo stile che sto cercando.Ma sarebbe bello poter fare lo stesso stile Qt.

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

Aggiornamento:

Quando avvio un debugger il programma è sospeso su readLine(), E non continuare fino a quando l'altra parte non chiude il FIFO.

E ottengo lo stesso usando ">>"

    line = in.readLine();
    in >> line;
È stato utile?

Soluzione

Usa lo stile c di basso livello e leggi un carattere alla volta.

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

Altri suggerimenti

Non so cosa non funziona ma puoi provare a eseguirne il debug utilizzando strace:

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

La prima riga registrerà tutte le chiamate di sistema di scrittura effettuate dal tuo programma di scrittura.La seconda linea funziona in modo simile.In questo modo puoi tracciare la chiamata di sistema ed essere sicuro che il tuo flush funzioni.

Se vedi chiamate ripetute per leggere, con tempi e dati corretti, allora hai un problema con QTextStream.

Cosa succede se non usi QTextStream, ma leggi direttamente dal file?

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

Potresti usare qualcosa del genere.

Potresti provare ad aprire il file dal lato del lettore con il file QIODevice::Unbuffered bandiera.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top