2010-10-05 9 views
6

Wie lese ich einen FIFO/Named Pipe Zeile für Zeile aus einer C++/Qt Linux App?Wie lese ich eine FIFO/Named Pipe Zeile für Zeile aus einer C++/Qt Linux App?

Heute kann ich öffnen und lesen von einem Fifo aus einem Qt-Programm, , aber ich kann nicht das Programm zum Lesen der Daten Zeile für Zeile. Qt liest die gesamte Datei, dh er wartet, bis der "Absender" seine Sitzung beendet.

Nehmen wir ein Beispiel mit einigen Shell-Befehlen, um zu zeigen, wie ich die App ausführen möchte.

zunächst eine Fifo erstellen

mkfifo MyPipe 

Dann können wir die Katze aus dem Fifo lesen verwenden

cat MyPipe 

Und dann wir

cat > MyPipe 

einige Daten in einer anderen Katze senden und dann fange an, etwas einzugeben, und jedes Mal, wenn du Enter drückst, kommt es beim Leser an. Und wenn Sie es dann mit Strg + D schließen, enden beide Seiten.

Jetzt ist der Absender einfach zu erstellen mit einem QTextStream, Sie müssen nur spülen, wenn Sie senden möchten.

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

Aber dann einen wenig Leser zu schreiben, die Zeile für Zeile gelesen ist, wo ich gerade bin stecken, alle meine Versuche mit dem Qt-lib enden mit, dass ich die Daten bekommen, aber nicht bis zum Absender verwendet file.close() auf dem FIFO. Nicht wenn er flush, wie wenn ich Katze zum Lesen benutze.

wie in diesem Beispiel:

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

Was mir fehlt?

Es fühlt sich an wie ich eine Art isReady oder lineAvailable auf den Strom oder etwas ähnliches verwenden müssen, aber ich kann nichts in der Dokumentation finden, das passt ...

/Danke


Hinweis:

Wenn ich mit dem niedrigen Niveau c Stil gehen und ein Zeichen an der Zeit, die ich den Stils im Meer erhalten tun lesen Rachen für. Aber es wäre nett, in der Lage zu sein, den gleichen Qt-Stil zu machen.

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

aktualisieren:

Wenn ich einen Debugger das Programm gestartet wird, auf dem readline hängen(), und nicht weiter, bis die andere Partei die Fifo schließt.

Und ich bekomme das gleiche tun mit „>>“

line = in.readLine(); 
    in >> line; 
+1

Kann es sein, dass die Pipe sofort gelesen wird und tatsächlich die Bildschirmausgabe gepuffert wird? Du hast 'qDebug() << line;' benutzt und sehe keine Spülung. –

+0

Guter Punkt, habe nicht darüber nachgedacht. – Johan

Antwort

4

Verwenden Sie den Low-Level-C-Stil und lesen Sie jeweils ein Zeichen.

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

'c' muss' int' sein andernfalls könnte es eine Endlosschleife sein, wenn 'char' unsigned ist (' EOF' ist negative ganze Zahl ("-1" typischerweise)). – jfs

2

Ich weiß nicht, was nicht funktioniert, aber Sie können versuchen, es zu debuggen mit strace:

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

der ersten Zeile protokolliert den gesamten Schreibsystemaufruf, der von Ihrem Schreibprogramm erstellt wurde. Die zweite Zeile funktioniert in ähnlicher Weise. Auf diese Weise können Sie den Systemaufruf verfolgen und sicherstellen, dass Ihre Spülung funktioniert.

Wenn Sie wiederholten Aufruf zu lesen, mit dem richtigen Timing und Daten sehen, dann haben Sie ein Problem mit QTextStream.

Was passiert, wenn Sie keinen QTextStream verwenden, sondern direkt aus der Datei lesen?

+0

strace ist nett, und ich habe ein "watch tail reader.log" in einem anderen Fenster gestartet und ich kann sehen, dass er die Daten bekommt, die ich ihm sende. – Johan

+0

@Johan: Sind Sie sicher, dass das Problem auf der Leserseite ist? – shodanex

+0

95% sicher, da, wenn ich die "Qt-Version" durch die "C-Version" ersetze, funktioniert. – Johan

1

Sie könnten versuchen, die Datei auf der Leserseite mit dem QIODevice::Unbuffered Flag zu öffnen.

+1

Gott-Idee, aber es ist immer noch das gleiche :( – Johan

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

Sie so etwas wie dies nutzen könnten.

+0

Die QFile-Implementierung von bytesAvailable funktioniert nicht für spezielle Dateien, einschließlich Named Pipes, und stürzt tatsächlich die Anwendung! –

Verwandte Themen