2009-08-13 9 views
7

Mit Qt zu lesen, ich bin versucht, den Inhalt des stdin-Stream in einer nicht-blockierenden Art und Weise zu lesen. Ich verwende den QSocketNotifier, um mich zu benachrichtigen, wenn der Socket einige neue Daten empfangen hat. Das Setup für den Anmelder sieht wie folgt aus:QTextStream mit stdin in einer nicht blockierenden Art und Weise

QSocketNotifier *pNot = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this); 
connect(pNot, SIGNAL(activated(int)), this, SLOT(onData())); 
pNot->setEnabled(true); 

Der onData() Schlitz wie folgt aussieht:

void CIPCListener::onData() 
{ 
    qDebug() << Q_FUNC_INFO; 
    QTextStream stream(stdin, QIODevice::ReadOnly); 

    QString str; 

    forever 
    { 
     fd_set stdinfd; 
     FD_ZERO(&stdinfd); 
     FD_SET(STDIN_FILENO, &stdinfd); 
     struct timeval tv; 
     tv.tv_sec = 0; 
     tv.tv_usec = 0; 
     int ready = select(1, &stdinfd, NULL, NULL, &tv); 
     if(ready > 0) 
     { 
      str += stream.readLine(); 
     } 
     else 
     { 
      break; 
     } 
    } 

    qDebug() << "Recieved data:" << str; 
} 

Wie man sehen kann ich versuchen, die select() Systemaufruf zu verwenden, um mir zu sagen, wenn Ich habe keine Daten mehr zum Lesen. In der Praxis passiert es jedoch, dass der Aufruf von select() 0 zurückgibt, nachdem ich die erste Textzeile gelesen habe. Wenn ich zum Beispiel 5 Zeilen Text in den stdin-Stream des Prozesses schreibe, lese ich immer nur die erste Zeile.

Was könnte das Problem sein?

+0

haben Sie ReadAll statt readline versucht? – Bob

+0

yup. Ich denke, es verwendet atEnd() intern, um zu erkennen, wann es das Ende des Streams erreicht hat. Das Ergebnis ist, dass es für immer blockiert. – Thomi

+1

ok, nur andere Sache, die ich versuche, denken kann, ist die aktuelle Implementierung Verschrottung (der select-Aufruf) und ähnlich, etwas zu tun, was der Assistent nicht finden Tools \ Assistent \ Tools \ Assistent \ Klappschlüssel * – Bob

Antwort

4

Linie Pufferung.

Standard wird Spülung nach einer "\ n". Wenn Sie 5 Zeilen in Ihren Prozess schreiben, wird Ihr Slot 5 Mal aufgerufen. Wenn Sie das vermeiden wollen, müssen Sie setbuf aufrufen (stdin, _IOFBF). Aber selbst dann ist es nicht garantiert, dass Sie beliebig große Datenmengen in einem Chunk lesen können.

Edit: Es wäre wahrscheinlich besser zu nutzen QTextStream :: atend() statt wählen, da QTextStream seinen eigenen internen Puffer hat.

+1

Sie können QTextStream :: atEnd() nicht auf stdin verwenden - die Qt-Dokumentation sagt das (siehe in der detaillierten Dokumentation für die Klasse). Siehe: http://doc.trolltech.com/4.5/qtextream.html#details – Thomi

1

Ich habe in anderer Antwort gefunden und Beispiel, das fast auf diese Frage paßt und mit vollständigem und einfachen Code:

https://stackoverflow.com/a/7389622/721929

ich es benutzt habe eine QT-Konsole basierte Anwendung mit einem Text-implementieren Menü zur Auswahl der Benutzerauswahl.